import BackoffPolicy from '../backoff/Backoff' ; import TimeoutScheduler from '../scheduler/TimeoutScheduler' ; import ReconnectController from './ReconnectController' ; export default class DefaultReconnectController implements ReconnectController { private shouldReconnect : boolean = true ; private onlyRestartPeerConnection : boolean = false ; private firstConnectionAttempted : boolean = false ; private firstConnectionAttemptTimestampMs : number = 0 ; private lastActiveTimestampMs : number = Infinity ; private _isFirstConnection : boolean = true ; private backoffTimer : TimeoutScheduler | null = null ; private backoffCancel : ( ) => void = null ; constructor ( private reconnectTimeoutMs , private backoffPolicy ) { this . reset ( ) ; } private timeSpentReconnectingMs ( ) { if ( ! this . firstConnectionAttempted ) { return 0 ; } return Date . now ( ) - this . firstConnectionAttemptTimestampMs ; } private hasPastReconnectDeadline ( ) { if ( Date . now ( ) - this . lastActiveTimestampMs >= this . reconnectTimeoutMs ) { return true ; } return this . timeSpentReconnectingMs ( ) >= this . reconnectTimeoutMs ; } reset ( ) { this . cancel ( ) ; this . shouldReconnect = true ; this . onlyRestartPeerConnection = false ; this . firstConnectionAttempted = false ; this . firstConnectionAttemptTimestampMs = 0 ; this . lastActiveTimestampMs = Infinity ; this . backoffPolicy . reset ( ) ; } startedConnectionAttempt ( isFirstConnection ) { this . _isFirstConnection = isFirstConnection ; if ( ! this . firstConnectionAttempted ) { this . firstConnectionAttempted = true ; this . firstConnectionAttemptTimestampMs = Date . now ( ) ; } } hasStartedConnectionAttempt ( ) { return this . firstConnectionAttempted ; } isFirstConnection ( ) { return this . _isFirstConnection ; } disableReconnect ( ) { this . shouldReconnect = false ; } enableRestartPeerConnection ( ) { this . onlyRestartPeerConnection = true ; } cancel ( ) { this . disableReconnect ( ) ; if ( this . backoffTimer ) { this . backoffTimer . stop ( ) ; if ( this . backoffCancel ) { this . backoffCancel ( ) ; this . backoffCancel = null ; } } } retryWithBackoff ( retryFunc , cancelFunc ) { const willRetry = this . shouldReconnect && ! this . hasPastReconnectDeadline ( ) ; if ( willRetry ) { this . backoffCancel = cancelFunc ; this . backoffTimer = new TimeoutScheduler ( this . backoffPolicy . nextBackoffAmountMs ( ) ) ; this . backoffTimer . start ( ( ) => { this . backoffCancel = null ; retryFunc ( ) ; } ) ; } return willRetry ; } shouldOnlyRestartPeerConnection ( ) { return this . onlyRestartPeerConnection ; } clone ( ) { return new DefaultReconnectController ( this . reconnectTimeoutMs , this . backoffPolicy ) ; } setLastActiveTimestampMs ( timestampMs ) { this . lastActiveTimestampMs = timestampMs ; } }