Quellcode durchsuchen

Add a timeout option to the `api.disco.refresh` function

And use it to set a lower timeout for disco info calls when joining a MUC.

Updates #3778
JC Brand vor 1 Monat
Ursprung
Commit
cdcaa927f8

+ 7 - 5
src/headless/plugins/disco/api.js

@@ -152,9 +152,10 @@ export default {
          * @method api.disco.info
          * @param {string} jid The Jabber ID of the entity to query
          * @param {string} [node] A specific node identifier associated with the JID
+         * @param {import('./types').DiscoInfoOptions} [options]
          * @returns {promise} Promise which resolves once we have a result from the server.
          */
-        info(jid, node) {
+        info(jid, node, options) {
             const attrs = { xmlns: Strophe.NS.DISCO_INFO };
             if (node) {
                 attrs.node = node;
@@ -164,7 +165,7 @@ export default {
                 'to': jid,
                 'type': 'get',
             }).c('query', attrs);
-            return api.sendIQ(info);
+            return api.sendIQ(info, options?.timeout);
         },
 
         /**
@@ -381,11 +382,12 @@ export default {
          * disco entity by refetching them from the server
          * @method api.disco.refresh
          * @param {string} jid The JID of the entity whose features are refreshed.
+         * @param {import('./types').DiscoInfoOptions} [options]
          * @returns {Promise} A promise which resolves once the features have been refreshed
          * @example
          * await api.disco.refresh('room@conference.example.org');
          */
-        async refresh(jid) {
+        async refresh(jid, options) {
             if (!jid) throw new TypeError('api.disco.refresh: You need to provide an entity JID');
 
             await api.waitUntil('discoInitialized');
@@ -400,10 +402,10 @@ export default {
                 if (!entity.waitUntilItemsFetched.isPending) {
                     entity.waitUntilItemsFetched = getOpenPromise();
                 }
-                entity.queryInfo();
+                entity.queryInfo(options);
             } else {
                 // Create it if it doesn't exist
-                entity = await api.disco.entities.create({ jid }, { ignore_cache: true });
+                entity = await api.disco.entities.create({ jid }, { ignore_cache: true, timeout: options.timeout });
             }
             return entity.waitUntilItemsFetched;
         },

+ 9 - 3
src/headless/plugins/disco/entity.js

@@ -102,9 +102,12 @@ class DiscoEntity extends Model {
         api.trigger('discoExtensionFieldDiscovered', field);
     }
 
+    /**
+     * @param {import('./types').FetchEntityFeaturesOptions} options
+     */
     async fetchFeatures(options) {
         if (options.ignore_cache) {
-            await this.queryInfo();
+            await this.queryInfo(options);
         } else {
             const store_id = this.features.browserStorage.name;
 
@@ -144,10 +147,13 @@ class DiscoEntity extends Model {
         }
     }
 
-    async queryInfo() {
+    /**
+     * @param {import('./types').DiscoInfoOptions} [options]
+     */
+    async queryInfo(options) {
         let stanza;
         try {
-            stanza = await api.disco.info(this.get('jid'), null);
+            stanza = await api.disco.info(this.get('jid'), null, options);
         } catch (iq) {
             if (u.isElement(iq)) {
                 const e = await parseErrorStanza(iq);

+ 8 - 0
src/headless/plugins/disco/types.ts

@@ -0,0 +1,8 @@
+export type DiscoInfoOptions = {
+    timeout?: number;
+}
+
+export type FetchEntityFeaturesOptions = {
+    timeout?: number;
+    ignore_cache?: boolean;
+}

+ 10 - 4
src/headless/plugins/muc/muc.js

@@ -50,6 +50,8 @@ import MUCSession from './session';
 
 const { u, stx } = converse.env;
 
+const DISCO_INFO_TIMEOUT_ON_JOIN = 5000;
+
 /**
  * Represents a groupchat conversation.
  */
@@ -192,7 +194,9 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
         // Set this early, so we don't rejoin in onHiddenChange
         this.session.save('connection_status', ROOMSTATUS.CONNECTING);
 
-        const is_new = (await this.refreshDiscoInfo()) instanceof ItemNotFoundError;
+        const result = await this.refreshDiscoInfo({ timeout: DISCO_INFO_TIMEOUT_ON_JOIN });
+        const is_new = result instanceof ItemNotFoundError;
+
         nick = await this.getAndPersistNickname(nick);
         if (!nick) {
             safeSave(this.session, { 'connection_status': ROOMSTATUS.NICKNAME_REQUIRED });
@@ -1254,10 +1258,11 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
      * Refresh the disco identity, features and fields for this {@link MUC}.
      * *features* are stored on the features {@link Model} attribute on this {@link MUC}.
      * *fields* are stored on the config {@link Model} attribute on this {@link MUC}.
+     * @param {import('@converse/headless/plugins/disco/types').DiscoInfoOptions} [options]
      * @returns {Promise}
      */
-    async refreshDiscoInfo() {
-        const result = await api.disco.refresh(this.get('jid'));
+    async refreshDiscoInfo(options) {
+        const result = await api.disco.refresh(this.get('jid'), options);
         if (result instanceof StanzaError) {
             return result;
         }
@@ -1738,7 +1743,8 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
             <iq to="${this.get('jid')}" type="get" xmlns="jabber:client">
                 <query xmlns="${Strophe.NS.DISCO_INFO}" node="x-roomuser-item"/>
             </iq>`;
-        const result = await api.sendIQ(stanza, null, false);
+
+        const result = await api.sendIQ(stanza, DISCO_INFO_TIMEOUT_ON_JOIN, false);
         if (u.isErrorObject(result)) {
             throw result;
         }

+ 1 - 0
src/headless/shared/api/send.js

@@ -19,6 +19,7 @@ export default {
     send(stanza) {
         const { api } = _converse;
         if (!api.connection.connected()) {
+            // TODO: queue unsent messages and send once we're connected again
             log.warn("Not sending stanza because we're not connected!");
             log.warn(Strophe.serialize(stanza));
             return;

+ 4 - 2
src/headless/types/plugins/disco/api.d.ts

@@ -65,9 +65,10 @@ declare namespace _default {
          * @method api.disco.info
          * @param {string} jid The Jabber ID of the entity to query
          * @param {string} [node] A specific node identifier associated with the JID
+         * @param {import('./types').DiscoInfoOptions} [options]
          * @returns {promise} Promise which resolves once we have a result from the server.
          */
-        export function info(jid: string, node?: string): Promise<any>;
+        export function info(jid: string, node?: string, options?: import("./types").DiscoInfoOptions): Promise<any>;
         /**
          * Query for items associated with an XMPP entity
          *
@@ -190,11 +191,12 @@ declare namespace _default {
          * disco entity by refetching them from the server
          * @method api.disco.refresh
          * @param {string} jid The JID of the entity whose features are refreshed.
+         * @param {import('./types').DiscoInfoOptions} [options]
          * @returns {Promise} A promise which resolves once the features have been refreshed
          * @example
          * await api.disco.refresh('room@conference.example.org');
          */
-        export function refresh(jid: string): Promise<any>;
+        export function refresh(jid: string, options?: import("./types").DiscoInfoOptions): Promise<any>;
         /**
          * Return all the features associated with a disco entity
          *

+ 8 - 2
src/headless/types/plugins/disco/entity.d.ts

@@ -46,8 +46,14 @@ declare class DiscoEntity extends Model {
     getFeature(feature: string): Promise<this>;
     onFeatureAdded(feature: any): void;
     onFieldAdded(field: any): void;
-    fetchFeatures(options: any): Promise<void>;
-    queryInfo(): Promise<void>;
+    /**
+     * @param {import('./types').FetchEntityFeaturesOptions} options
+     */
+    fetchFeatures(options: import("./types").FetchEntityFeaturesOptions): Promise<void>;
+    /**
+     * @param {import('./types').DiscoInfoOptions} [options]
+     */
+    queryInfo(options?: import("./types").DiscoInfoOptions): Promise<void>;
     /**
      * @param {Element} stanza
      */

+ 8 - 0
src/headless/types/plugins/disco/types.d.ts

@@ -0,0 +1,8 @@
+export type DiscoInfoOptions = {
+    timeout?: number;
+};
+export type FetchEntityFeaturesOptions = {
+    timeout?: number;
+    ignore_cache?: boolean;
+};
+//# sourceMappingURL=types.d.ts.map

+ 2 - 1
src/headless/types/plugins/muc/muc.d.ts

@@ -539,9 +539,10 @@ declare class MUC extends MUC_base {
      * Refresh the disco identity, features and fields for this {@link MUC}.
      * *features* are stored on the features {@link Model} attribute on this {@link MUC}.
      * *fields* are stored on the config {@link Model} attribute on this {@link MUC}.
+     * @param {import('@converse/headless/plugins/disco/types').DiscoInfoOptions} [options]
      * @returns {Promise}
      */
-    refreshDiscoInfo(): Promise<any>;
+    refreshDiscoInfo(options?: import("@converse/headless/plugins/disco/types").DiscoInfoOptions): Promise<any>;
     /**
      * Fetch the *extended* MUC info from the server and cache it locally
      * https://xmpp.org/extensions/xep-0045.html#disco-roominfo