Move reconnection code to Connection class

And avoid calling `tearDown` twice
This commit is contained in:
JC Brand 2022-02-02 13:49:02 +01:00
parent cb0b1765f3
commit d3fa925bff
4 changed files with 74 additions and 70 deletions

View File

@ -1,17 +1,15 @@
# Changelog
## 9.0.1 (2021-??-??)
## 9.0.1 (Unreleased)
- Updated translations: lt
- Increased stanza timeout from 10 to 20 seconds
- Replace various font icons with SVG icons
- #1761: Add a new dark theme based on the [Dracula](https://draculatheme.com/) theme
- #2751: Media not rendered when Converse runs in a browser extension
- #2786: Fix webpack configuration not working on Windows OS
- #2789: Implement new hook parseMessageForCommands for plugins to add custom
- #2789: Implement new hook `parseMessageForCommands` for plugins to add custom commands
### New hooks and events
- New hook: [parseMessageForCommands](https://conversejs.org/docs/html/api/-_converse.html#event:parseMessageForCommands)
## 9.0.0 (2021-11-26)
@ -49,7 +47,6 @@ Three config settings have been obsoleted:
- show_images_inline
- muc_show_ogp_unfurls
### Breaking Changes
Configuration settings are no longer available on the `_converse` object.

View File

@ -137,47 +137,9 @@ export const api = _converse.api = {
* @method reconnect
* @memberOf _converse.api.connection
*/
async reconnect () {
const conn_status = _converse.connfeedback.get('connection_status');
if (api.settings.get("authentication") === _converse.ANONYMOUS) {
await tearDown();
await clearSession();
}
if (conn_status === Strophe.Status.CONNFAIL) {
// When reconnecting with a new transport, we call setUserJID
// so that a new resource is generated, to avoid multiple
// server-side sessions with the same resource.
//
// We also call `_proto._doDisconnect` so that connection event handlers
// for the old transport are removed.
if (api.connection.isType('websocket') && api.settings.get('bosh_service_url')) {
await setUserJID(_converse.bare_jid);
_converse.connection._proto._doDisconnect();
_converse.connection._proto = new Strophe.Bosh(_converse.connection);
_converse.connection.service = api.settings.get('bosh_service_url');
} else if (api.connection.isType('bosh') && api.settings.get("websocket_url")) {
if (api.settings.get("authentication") === _converse.ANONYMOUS) {
// When reconnecting anonymously, we need to connect with only
// the domain, not the full JID that we had in our previous
// (now failed) session.
await setUserJID(api.settings.get("jid"));
} else {
await setUserJID(_converse.bare_jid);
}
_converse.connection._proto._doDisconnect();
_converse.connection._proto = new Strophe.Websocket(_converse.connection);
_converse.connection.service = api.settings.get("websocket_url");
}
} else if (conn_status === Strophe.Status.AUTHFAIL && api.settings.get("authentication") === _converse.ANONYMOUS) {
// When reconnecting anonymously, we need to connect with only
// the domain, not the full JID that we had in our previous
// (now failed) session.
await setUserJID(api.settings.get("jid"));
}
reconnect () {
if (_converse.connection?.reconnecting) {
_converse.connection.debouncedReconnect();
return _converse.connection.debouncedReconnect();
} else {
return _converse.connection.reconnect();
}
@ -571,19 +533,6 @@ export const api = _converse.api = {
};
export async function tearDown () {
await _converse.api.trigger('beforeTearDown', {'synchronous': true});
window.removeEventListener('click', _converse.onUserActivity);
window.removeEventListener('focus', _converse.onUserActivity);
window.removeEventListener('keypress', _converse.onUserActivity);
window.removeEventListener('mousemove', _converse.onUserActivity);
window.removeEventListener(_converse.unloadevent, _converse.onUserActivity);
window.clearInterval(_converse.everySecondTrigger);
_converse.api.trigger('afterTearDown');
return _converse;
}
_converse.shouldClearCache = () => (
!_converse.config.get('trusted') ||
api.settings.get('clear_cache_on_logout') ||

View File

@ -2,11 +2,12 @@ import debounce from 'lodash-es/debounce';
import isElement from 'lodash-es/isElement';
import log from "../log.js";
import sizzle from 'sizzle';
import { BOSH_WAIT } from '@converse/headless/shared/constants.js';
import { Strophe } from 'strophe.js/src/core';
import { _converse, api, clearSession, tearDown } from "../core.js";
import { _converse, api, clearSession } from "../core.js";
import { getOpenPromise } from '@converse/openpromise';
import { setUserJID, } from '@converse/headless/utils/init.js';
import { BOSH_WAIT } from '@converse/headless/shared/constants.js';
import { tearDown } from '@converse/headless/utils/core.js';
/**
@ -18,7 +19,7 @@ export class Connection extends Strophe.Connection {
constructor (service, options) {
super(service, options);
this.debouncedReconnect = debounce(this.reconnect, 2000);
this.debouncedReconnect = debounce(this.reconnect, 3000);
}
static generateResource () {
@ -107,23 +108,67 @@ export class Connection extends Strophe.Connection {
super.connect(jid, password, callback || this.onConnectStatusChanged, BOSH_WAIT);
}
/**
* Switch to a different transport if a service URL is available for it.
*
* When reconnecting with a new transport, we call setUserJID
* so that a new resource is generated, to avoid multiple
* server-side sessions with the same resource.
*
* We also call `_proto._doDisconnect` so that connection event handlers
* for the old transport are removed.
*/
async switchTransport () {
if (api.connection.isType('websocket') && api.settings.get('bosh_service_url')) {
await setUserJID(_converse.bare_jid);
this._proto._doDisconnect();
this._proto = new Strophe.Bosh(this);
this.service = api.settings.get('bosh_service_url');
} else if (api.connection.isType('bosh') && api.settings.get("websocket_url")) {
if (api.settings.get("authentication") === _converse.ANONYMOUS) {
// When reconnecting anonymously, we need to connect with only
// the domain, not the full JID that we had in our previous
// (now failed) session.
await setUserJID(api.settings.get("jid"));
} else {
await setUserJID(_converse.bare_jid);
}
this._proto._doDisconnect();
this._proto = new Strophe.Websocket(this);
this.service = api.settings.get("websocket_url");
}
}
async reconnect () {
const { __ } = _converse;
log.debug('RECONNECTING: the connection has dropped, attempting to reconnect.');
this.reconnecting = true;
await tearDown();
const conn_status = _converse.connfeedback.get('connection_status');
if (conn_status === Strophe.Status.CONNFAIL) {
this.switchTransport();
} else if (conn_status === Strophe.Status.AUTHFAIL && api.settings.get("authentication") === _converse.ANONYMOUS) {
// When reconnecting anonymously, we need to connect with only
// the domain, not the full JID that we had in our previous
// (now failed) session.
await setUserJID(api.settings.get("jid"));
}
const { __ } = _converse;
this.setConnectionStatus(
Strophe.Status.RECONNECTING,
__('The connection has dropped, attempting to reconnect.')
);
/**
* Triggered when the connection has dropped, but Converse will attempt
* to reconnect again.
*
* @event _converse#will-reconnect
*/
* Triggered when the connection has dropped, but Converse will attempt
* to reconnect again.
* @event _converse#will-reconnect
*/
api.trigger('will-reconnect');
this.reconnecting = true;
await tearDown();
if (api.settings.get("authentication") === _converse.ANONYMOUS) {
await clearSession();
}
return api.user.login();
}

View File

@ -38,6 +38,19 @@ export function isUniView () {
}
export async function tearDown () {
await _converse.api.trigger('beforeTearDown', {'synchronous': true});
window.removeEventListener('click', _converse.onUserActivity);
window.removeEventListener('focus', _converse.onUserActivity);
window.removeEventListener('keypress', _converse.onUserActivity);
window.removeEventListener('mousemove', _converse.onUserActivity);
window.removeEventListener(_converse.unloadevent, _converse.onUserActivity);
window.clearInterval(_converse.everySecondTrigger);
_converse.api.trigger('afterTearDown');
return _converse;
}
/**
* The utils object
* @namespace u