mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
add comments to reconnector.
This commit is contained in:
parent
7a7041625a
commit
e2db39fe69
@ -74,7 +74,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
||||
|
||||
this._onCloseHandle = this.close.bind(this)
|
||||
|
||||
// bind events to all reconnecters
|
||||
// bind events to all reconnectors
|
||||
Object.values(this._reconnector).forEach((r) => {
|
||||
r.on('connect', this._onConnectHandle)
|
||||
r.on('disconnect', this._onDisconnectHandle)
|
||||
@ -179,7 +179,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
||||
|
||||
Vue.set(this._state, 'status', 'connecting')
|
||||
|
||||
// open all reconnecters
|
||||
// open all reconnectors with deferred connection
|
||||
Object.values(this._reconnector).forEach((r) => r.open(true))
|
||||
|
||||
this._reconnector.websocket.connect()
|
||||
@ -189,6 +189,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
||||
if (this._open) {
|
||||
this._open = false
|
||||
|
||||
// set state to disconnected
|
||||
Vue.set(this._state.websocket, 'connected', false)
|
||||
Vue.set(this._state.webrtc, 'connected', false)
|
||||
Vue.set(this._state, 'status', 'disconnected')
|
||||
@ -196,7 +197,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
||||
this.emit('close', error)
|
||||
}
|
||||
|
||||
// close all reconnecters
|
||||
// close all reconnectors
|
||||
Object.values(this._reconnector).forEach((r) => r.close())
|
||||
}
|
||||
|
||||
@ -206,16 +207,17 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
||||
// TODO: Use server side congestion control.
|
||||
this.webrtc.off('stats', this._webrtcCongestionControlHandle)
|
||||
|
||||
// unbind events from all reconnecters
|
||||
// unbind events from all reconnectors
|
||||
Object.values(this._reconnector).forEach((r) => {
|
||||
r.off('connect', this._onConnectHandle)
|
||||
r.off('disconnect', this._onDisconnectHandle)
|
||||
r.off('close', this._onCloseHandle)
|
||||
})
|
||||
|
||||
// destroy all reconnecters
|
||||
// destroy all reconnectors
|
||||
Object.values(this._reconnector).forEach((r) => r.destroy())
|
||||
|
||||
// set state to disconnected
|
||||
Vue.set(this._state.websocket, 'connected', false)
|
||||
Vue.set(this._state.webrtc, 'connected', false)
|
||||
Vue.set(this._state, 'status', 'disconnected')
|
||||
|
@ -23,6 +23,25 @@ export abstract class ReconnectorAbstract extends EventEmitter<ReconnectorAbstra
|
||||
public abstract destroy(): void
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reconnector handles reconnection logic according to supplied config for an abstract class. It can reconnect anything that:
|
||||
- can be connected to
|
||||
- can send event once it is connected to
|
||||
- can be disconnected from
|
||||
- can send event once it is disconnected from
|
||||
- can provide information at any moment if it is connected to or not
|
||||
|
||||
Reconnector creates one additional abstract layer for a user. User can open and close a connection. If the connection is open,
|
||||
when connection will be disconnected, reconnector will attempt to connect to it again. Once connection is closed, no further
|
||||
events will be emitted and connection will be disconnected.
|
||||
- When using deferred connection in opening function, reconnector does not try to connect when opening a connection. This is
|
||||
the initial state, when reconnector is not connected but no reconnect attempts are in progress, since there has not been
|
||||
any disconnect even. It is up to user to call initial connect attempt.
|
||||
- Events 'open' and 'close' will be fired exactly once, no matter how many times open() and close() funxtions were called.
|
||||
- Events 'connecŧ' and 'disconnect' can fire throughout open connection at any time.
|
||||
|
||||
*/
|
||||
export interface ReconnectorEvents {
|
||||
open: () => void
|
||||
connect: () => void
|
||||
@ -48,6 +67,7 @@ export class Reconnector extends EventEmitter<ReconnectorEvents> {
|
||||
) {
|
||||
super()
|
||||
|
||||
// setup default config values
|
||||
this._config = {
|
||||
max_reconnects: 10,
|
||||
timeout_ms: 1500,
|
||||
@ -55,6 +75,10 @@ export class Reconnector extends EventEmitter<ReconnectorEvents> {
|
||||
...config,
|
||||
}
|
||||
|
||||
// register connect and disconnect handlers with current class
|
||||
// as 'this' context, store them to a variable so that they
|
||||
// can be later unregistered
|
||||
|
||||
this._onConnectHandle = this.onConnect.bind(this)
|
||||
this._conn.on('connect', this._onConnectHandle)
|
||||
|
||||
@ -62,27 +86,33 @@ export class Reconnector extends EventEmitter<ReconnectorEvents> {
|
||||
this._conn.on('disconnect', this._onDisconnectHandle)
|
||||
}
|
||||
|
||||
private onConnect() {
|
||||
private clearTimeout() {
|
||||
if (this._timeout) {
|
||||
window.clearTimeout(this._timeout)
|
||||
this._timeout = undefined
|
||||
}
|
||||
}
|
||||
|
||||
private onConnect() {
|
||||
this.clearTimeout()
|
||||
|
||||
// only if connection is open, fire connect event
|
||||
if (this._open) {
|
||||
this._last_connected = new Date()
|
||||
this._total_reconnects = 0
|
||||
this.emit('connect')
|
||||
} else {
|
||||
// in this case we are connected but this connection
|
||||
// has been closed, so we simply disconnect again
|
||||
this._conn.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
private onDisconnect() {
|
||||
if (this._timeout) {
|
||||
window.clearTimeout(this._timeout)
|
||||
this._timeout = undefined
|
||||
}
|
||||
this.clearTimeout()
|
||||
|
||||
// only if connection is open, fire disconnect event
|
||||
// and start reconnecteing logic
|
||||
if (this._open) {
|
||||
this.emit('disconnect')
|
||||
this.reconnect()
|
||||
@ -110,18 +140,21 @@ export class Reconnector extends EventEmitter<ReconnectorEvents> {
|
||||
}
|
||||
|
||||
public set config(conf: ReconnectorConfig) {
|
||||
this._config = { ...conf }
|
||||
this._config = { ...this._config, ...conf }
|
||||
|
||||
if (this._config.max_reconnects <= this._total_reconnects) {
|
||||
this.close(new Error('reconnection config changed'))
|
||||
}
|
||||
}
|
||||
|
||||
// allows future reconnect attempts and connects if not set
|
||||
// deferred connection to true
|
||||
public open(deferredConnection = false): void {
|
||||
if (this._timeout) {
|
||||
window.clearTimeout(this._timeout)
|
||||
this._timeout = undefined
|
||||
}
|
||||
this.clearTimeout()
|
||||
|
||||
// assuming open event can fire multiple times, we need to
|
||||
// ensure, that open event get fired only once along with
|
||||
// resetting total reconnects counter
|
||||
|
||||
if (!this._open) {
|
||||
this._open = true
|
||||
@ -134,11 +167,13 @@ export class Reconnector extends EventEmitter<ReconnectorEvents> {
|
||||
}
|
||||
}
|
||||
|
||||
// disconnects and forbids future reconnect attempts
|
||||
public close(error?: Error): void {
|
||||
if (this._timeout) {
|
||||
window.clearTimeout(this._timeout)
|
||||
this._timeout = undefined
|
||||
}
|
||||
this.clearTimeout()
|
||||
|
||||
// assuming close event can fire multiple times, the same
|
||||
// precautions need to be taken as in open event, so that
|
||||
// close event fires only once
|
||||
|
||||
if (this._open) {
|
||||
this._open = false
|
||||
@ -146,38 +181,39 @@ export class Reconnector extends EventEmitter<ReconnectorEvents> {
|
||||
this.emit('close', error)
|
||||
}
|
||||
|
||||
// if connected, tries to disconnect even if it has been
|
||||
// called multiple times by user
|
||||
|
||||
if (this._conn.connected) {
|
||||
this._conn.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
// tries to connect and calls on disconnected if it could not
|
||||
// connect within specified timeout according to config
|
||||
public connect(): void {
|
||||
if (this._timeout) {
|
||||
window.clearTimeout(this._timeout)
|
||||
this._timeout = undefined
|
||||
}
|
||||
this.clearTimeout()
|
||||
|
||||
this._conn.connect()
|
||||
this._timeout = window.setTimeout(this.onDisconnect.bind(this), this._config.timeout_ms)
|
||||
}
|
||||
|
||||
// tries to connect with specified backoff time if
|
||||
// maximum reconnect theshold was not exceeded, otherwise
|
||||
// closes the connection with an error message
|
||||
public reconnect(): void {
|
||||
if (this._timeout) {
|
||||
window.clearTimeout(this._timeout)
|
||||
this._timeout = undefined
|
||||
}
|
||||
this.clearTimeout()
|
||||
|
||||
this._total_reconnects++
|
||||
|
||||
if (this._config.max_reconnects > this._total_reconnects || this._config.max_reconnects == -1) {
|
||||
if (this._config.max_reconnects > ++this._total_reconnects || this._config.max_reconnects == -1) {
|
||||
this._timeout = window.setTimeout(this.connect.bind(this), this._config.backoff_ms)
|
||||
} else {
|
||||
this.close(new Error('reconnection failed'))
|
||||
}
|
||||
}
|
||||
|
||||
// closes connection and unregisters all events
|
||||
public destroy() {
|
||||
this.close()
|
||||
this.close(new Error('connection destroyed'))
|
||||
|
||||
this._conn.off('connect', this._onConnectHandle)
|
||||
this._conn.off('disconnect', this._onDisconnectHandle)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as webrtcTypes from './webrtc'
|
||||
import * as reconnecterTypes from './reconnector'
|
||||
import * as reconnectorTypes from './reconnector'
|
||||
|
||||
export default interface State {
|
||||
authenticated: boolean
|
||||
@ -39,7 +39,7 @@ export interface WebRTC {
|
||||
videos: string[]
|
||||
}
|
||||
|
||||
export interface ReconnectorConfig extends reconnecterTypes.ReconnectorConfig {}
|
||||
export interface ReconnectorConfig extends reconnectorTypes.ReconnectorConfig {}
|
||||
|
||||
export interface WebRTCStats extends webrtcTypes.WebRTCStats {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user