git » sdk » commit cc8cd26

Speed up initial MUC sync

author Stephen Paul Weber
2025-03-24 02:51:52 UTC
committer Stephen Paul Weber
2025-03-24 02:51:52 UTC
parent 79a94ac0e26b73e2ef8e6a9dec68c0aa4267d585

Speed up initial MUC sync

This shaves ~3 seconds off initial MUC sync in testing.

Don't do a self ping on first connect: we're coming from offline so the
odds of a success ping are very low it's just a wasted round trip.

Don't do disco refresh before join unless we've never done a disco on
this room before. Push all disco refresh to 10 seconds in the future so
they don't slow down our initial sync.

Send MAM request right after join request instead of waiting for 110.
This could case a small race condition if MAM returns before we start
getting live messages but it's pretty small since join has already
started by the time MAM starts here. This particular change saves us a
bit under a second of time so that's the tradeoff.

snikket/Chat.hx +22 -18
snikket/Client.hx +17 -1

diff --git a/snikket/Chat.hx b/snikket/Chat.hx
index fb58b58..1c2db8d 100644
--- a/snikket/Chat.hx
+++ b/snikket/Chat.hx
@@ -960,21 +960,8 @@ class Channel extends Chat {
 						if (err.name == "service-unavailable" || err.name == "feature-not-implemented") return selfPingSuccess(); // Error, success!
 						if (err.name == "remote-server-not-found" || err.name == "remote-server-timeout") return selfPingSuccess(); // Timeout, retry later
 						if (err.name == "item-not-found") return selfPingSuccess(); // Nick was changed?
-						presence = []; // About to ask for a fresh set
-						_nickInUse = null;
-						inSync = false;
-						client.trigger("chats/update", [this]);
-						final desiredFullJid = JID.parse(chatId).withResource(client.displayName());
-						client.sendPresence(
-							desiredFullJid.asString(),
-							(stanza) -> {
-								stanza.tag("x", { xmlns: "http://jabber.org/protocol/muc" });
-								if (disco.features.contains("urn:xmpp:mam:2")) stanza.tag("history", { maxchars: "0" }).up();
-								// TODO: else since (last message we know about)
-								stanza.up();
-								return stanza;
-							}
-						);
+						trace("SYNC: self-ping fail, join", chatId);
+						join();
 					} else {
 						selfPingSuccess();
 					}
@@ -983,6 +970,26 @@ class Channel extends Chat {
 		});
 	}
 
+	@:allow(snikket)
+	private function join() {
+		presence = []; // About to ask for a fresh set
+		_nickInUse = null;
+		inSync = false;
+		client.trigger("chats/update", [this]);
+		final desiredFullJid = JID.parse(chatId).withResource(client.displayName());
+		client.sendPresence(
+			desiredFullJid.asString(),
+			(stanza) -> {
+				stanza.tag("x", { xmlns: "http://jabber.org/protocol/muc" });
+				if (disco.features.contains("urn:xmpp:mam:2")) stanza.tag("history", { maxchars: "0" }).up();
+				// TODO: else since (last message we know about)
+				stanza.up();
+				return stanza;
+			}
+		);
+		persistence.lastId(client.accountId(), chatId, doSync);
+	}
+
 	private function selfPingSuccess() {
 		if (nickInUse() != client.displayName()) {
 			final desiredFullJid = JID.parse(chatId).withResource(client.displayName());
@@ -1011,9 +1018,6 @@ class Channel extends Chat {
 		}
 		super.setPresence(resource, presence);
 		final tripleThree = presence?.mucUser?.allTags("status").find((status) -> status.attr.get("code") == "333");
-		if (!inSync && sync == null && oneTen != null) {
-			persistence.lastId(client.accountId(), chatId, doSync);
-		}
 		if (oneTen != null && tripleThree != null) {
 			selfPing(true);
 		}
diff --git a/snikket/Client.hx b/snikket/Client.hx
index f204c03..8152c2e 100644
--- a/snikket/Client.hx
+++ b/snikket/Client.hx
@@ -719,7 +719,7 @@ class Client extends EventEmitter {
 								.up()
 						);
 						sendPresence();
-						pingAllChannels(true);
+						joinAllChannels();
 					}
 					this.trigger("status/online", {});
 					trace("SYNC: done");
@@ -1508,4 +1508,20 @@ class Client extends EventEmitter {
 			channel?.selfPing(refresh || channel?.disco == null);
 		}
 	}
+
+	private function joinAllChannels() {
+		for (chat in getChats()) {
+			final channel = Std.downcast(chat, Channel);
+			if (channel != null) {
+				if (channel.disco.identities.length < 1) {
+					channel.refreshDisco(() -> {
+						channel.join();
+					});
+				} else {
+					channel.join();
+					haxe.Timer.delay(() -> channel.refreshDisco(), 30000);
+				}
+			}
+		}
+	}
 }