UNPKG

@skyway-sdk/rtc-api-client

Version:

The official Next Generation JavaScript SDK for SkyWay

146 lines 6.48 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EventJitterBuffer = exports.EventObserverImpl = void 0; const common_1 = require("@skyway-sdk/common"); const errors_1 = require("../errors"); const util_1 = require("../util"); const log = new common_1.Logger('packages/rtc-api-client/src/infrastructure/eventObserver.ts'); class EventObserverImpl { constructor(appId, client, channelDto, config) { this.onEvent = new common_1.Event(); this._disposer = []; const eventBuffer = new EventJitterBuffer(channelDto.version, (expectNextVersion) => __awaiter(this, void 0, void 0, function* () { // ここで回復できなければシステム継続不能 yield client.subscribeChannelEvents({ appId, channelId: channelDto.id, offset: expectNextVersion, }); yield new Promise((r) => setTimeout(r, config.eventSubscribeTimeout)); if (eventBuffer.packetLostHappened) { log.error((0, util_1.createError)({ operationName: 'EventObserverImpl.eventJitterBuffer', info: Object.assign(Object.assign({}, errors_1.errors.internalError), { detail: 'failed to resolve event lost' }), channelId: channelDto.id, appId, path: log.prefix, })); } })); this._disposer = [ client.onEvent.add(({ channelId, event }) => __awaiter(this, void 0, void 0, function* () { if (channelId === channelDto.id) { eventBuffer.push({ event, version: event.data.channel.version }); } })).removeListener, eventBuffer.onEvent.add((e) => { this.onEvent.emit(e); }).removeListener, ]; } dispose() { this._disposer.forEach((d) => { d(); }); this.onEvent.removeAllListeners(); } } exports.EventObserverImpl = EventObserverImpl; /**@internal */ class EventJitterBuffer { constructor(presentVersion, onPacketLost, packetLifetime = 1000) { this.presentVersion = presentVersion; this.onPacketLost = onPacketLost; this.packetLifetime = packetLifetime; this.onEvent = new common_1.Event(); this.eventBuffer = {}; this.packetLostHappened = false; } get expectNextVersion() { return this.presentVersion + 1; } push(eventFrame) { const incomingVersion = eventFrame.version; if (incomingVersion < this.expectNextVersion) { log.debug('duplicate event', Object.assign(Object.assign({}, eventFrame), { presentVersion: this.presentVersion })); return; } if (incomingVersion > this.expectNextVersion) { log.debug('maybe miss order event received', Object.assign(Object.assign({}, eventFrame), { presentVersion: this.presentVersion })); this.eventBuffer[incomingVersion] = eventFrame; this.handlePacketLifetime(); return; } // expected version event received if (this.packetLostHappened) { log.warn('event packetLost resolved', (0, util_1.createWarnPayload)({ operationName: 'EventJitterBuffer.push', detail: 'event packetLost resolved', payload: { eventFrame }, })); this.packetLostHappened = false; } this.eventBuffer[incomingVersion] = eventFrame; this.resolveEvents(); } handlePacketLifetime() { const [oldestBufferedEvent] = Object.keys(this.eventBuffer) .sort() .map((key) => this.eventBuffer[Number(key)]); if (this.packetLifeTimer === undefined && oldestBufferedEvent) { log.debug('set event packetLost timer', Object.assign(Object.assign({}, oldestBufferedEvent), { presentVersion: this.presentVersion })); this.packetLifeTimer = setTimeout(() => __awaiter(this, void 0, void 0, function* () { if (this.presentVersion < oldestBufferedEvent.version) { log.warn('event packetLost', (0, util_1.createWarnPayload)({ operationName: 'EventJitterBuffer.handlePacketLifetime', detail: 'eventPacket lost', payload: { oldestBufferedEvent, eventBufferLength: Object.keys(this.eventBuffer).length, presentVersion: this.presentVersion, }, })); if (this.packetLostHappened) { return; } else { this.packetLostHappened = true; yield this.onPacketLost(this.expectNextVersion); } } this.packetLifeTimer = undefined; this.handlePacketLifetime(); }), this.packetLifetime); } } resolveEvents() { const resolve = []; for (let i = this.expectNextVersion;; i++) { const frame = this.eventBuffer[i]; if (frame) { resolve.push(frame); delete this.eventBuffer[i]; } else { break; } } if (resolve.length > 0) { this.presentVersion = resolve.slice(-1)[0].version; resolve.forEach((frame) => { this.onEvent.emit(frame.event); }); } } } exports.EventJitterBuffer = EventJitterBuffer; //# sourceMappingURL=eventObserver.js.map