periodically renew endpoints

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/persistance/UnifiedPushDatabase.java |  7 
src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java      | 26 
2 files changed, 30 insertions(+), 3 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/persistance/UnifiedPushDatabase.java 🔗

@@ -19,6 +19,7 @@ import org.jetbrains.annotations.NotNull;
 import java.util.List;
 
 import eu.siacs.conversations.Config;
+import eu.siacs.conversations.services.UnifiedPushBroker;
 
 public class UnifiedPushDatabase extends SQLiteOpenHelper {
     private static final String DATABASE_NAME = "unified-push-distributor";
@@ -84,8 +85,7 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
 
     public List<PushTarget> getRenewals(final String account, final String transport) {
         final ImmutableList.Builder<PushTarget> renewalBuilder = ImmutableList.builder();
-        // TODO use a date somewhat in the future to account for period renewal triggers
-        final long expiration = System.currentTimeMillis();
+        final long expiration = System.currentTimeMillis() + UnifiedPushBroker.TIME_TO_RENEW;
         final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
         try (final Cursor cursor =
                 sqLiteDatabase.query(
@@ -108,13 +108,14 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
 
     public ApplicationEndpoint getEndpoint(
             final String account, final String transport, final String instance) {
+        final long expiration = System.currentTimeMillis() + UnifiedPushBroker.TIME_TO_RENEW;
         final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
         try (final Cursor cursor =
                 sqLiteDatabase.query(
                         "push",
                         new String[] {"application", "endpoint"},
                         "account = ? AND transport = ? AND instance = ? AND endpoint IS NOT NULL AND expiration >= "
-                                + System.currentTimeMillis(),
+                                + expiration,
                         new String[] {account, transport, instance},
                         null,
                         null,

src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java 🔗

@@ -15,6 +15,9 @@ import com.google.common.io.BaseEncoding;
 import java.nio.charset.StandardCharsets;
 import java.text.ParseException;
 import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
@@ -28,10 +31,24 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 
 public class UnifiedPushBroker {
 
+    // time to expiration before a renewal attempt is made (24 hours)
+    public static final long TIME_TO_RENEW = 86_400_000L;
+
+    // interval for the 'cron tob' that attempts renewals for everything that expires is lass than
+    // `TIME_TO_RENEW`
+    public static final long RENEWAL_INTERVAL = 3_600_000L;
+
+    private static final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
+
     private final XmppConnectionService service;
 
     public UnifiedPushBroker(final XmppConnectionService xmppConnectionService) {
         this.service = xmppConnectionService;
+        SCHEDULER.scheduleAtFixedRate(
+                this::renewUnifiedPushEndpoints,
+                RENEWAL_INTERVAL,
+                RENEWAL_INTERVAL,
+                TimeUnit.MILLISECONDS);
     }
 
     public void renewUnifiedPushEndpointsOnBind(final Account account) {
@@ -68,6 +85,13 @@ public class UnifiedPushBroker {
         final List<UnifiedPushDatabase.PushTarget> renewals =
                 unifiedPushDatabase.getRenewals(
                         account.getUuid(), transport.transport.toEscapedString());
+        Log.d(
+                Config.LOGTAG,
+                account.getJid().asBareJid()
+                        + ": "
+                        + renewals.size()
+                        + " UnifiedPush endpoints scheduled for renewal on "
+                        + transport.transport);
         for (final UnifiedPushDatabase.PushTarget renewal : renewals) {
             Log.d(
                     Config.LOGTAG,
@@ -110,6 +134,8 @@ public class UnifiedPushBroker {
                 return;
             }
             renewUnifiedPushEndpoint(transport, renewal, endpoint, expiration);
+        } else {
+            Log.d(Config.LOGTAG, "could not register UP endpoint " + response.getErrorCondition());
         }
     }