UNPKG

@neurosity/sdk

Version:
52 lines (51 loc) 2.89 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.deviceHasLostHeartbeat = exports.heartbeatAwareStatus = void 0; const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const operators_2 = require("rxjs/operators"); const fast_deep_equal_1 = __importDefault(require("fast-deep-equal")); const status_1 = require("../types/status"); const HEARTBEAT_UPDATE_INTERVAL = 30000; // 30 seconds - set by the OS const LOST_LOCAL_HEARTBEAT_AFTER = HEARTBEAT_UPDATE_INTERVAL * 2.5; // 75 seconds const LOST_REMOTE_HEARTBEAT_AFTER = 8.64e7; // 24 hours function heartbeatAwareStatus(status$) { const lastLocalHeartbeat$ = status$.pipe((0, operators_1.map)(({ lastHeartbeat }) => lastHeartbeat), (0, operators_2.distinctUntilChanged)(), (0, operators_1.map)(() => Date.now())); const lostHeartbeat$ = lastLocalHeartbeat$.pipe((0, operators_1.switchMap)(() => (0, rxjs_1.timer)(LOST_LOCAL_HEARTBEAT_AFTER)), (0, operators_1.map)(() => null), (0, operators_1.startWith)(null)); return (0, rxjs_1.combineLatest)({ status: status$, lostHeartbeat: lostHeartbeat$ // @important - do not remove, adeed for state synchronization, value not used }).pipe((0, operators_2.withLatestFrom)(lastLocalHeartbeat$), (0, operators_1.map)(([{ status }, lastLocalHeartbeat]) => { if (!lastLocalHeartbeat) { return status; } const lostHeartbeat = deviceHasLostHeartbeat(status, lastLocalHeartbeat); return lostHeartbeat ? Object.assign(Object.assign({}, status), { state: status_1.STATUS.OFFLINE }) : status; }), (0, operators_2.distinctUntilChanged)((a, b) => (0, fast_deep_equal_1.default)(a, b))); } exports.heartbeatAwareStatus = heartbeatAwareStatus; function deviceHasLostHeartbeat(status, lastLocalHeartbeat) { if (!("lastHeartbeat" in status)) { return false; } // We are converting the heartbeat to the local time because the previous // implementation that used the server timestamp had bug where SDK clients // running on hardware with drifted/out-of-sync clocks (cough cough Android) // would override the state to offline when the heartbeat was active. const lostLocalHeartbeat = Date.now() - lastLocalHeartbeat > LOST_LOCAL_HEARTBEAT_AFTER; if (lostLocalHeartbeat) { return true; } // Addresses devices with wrongful "online" state. This rarely happens, the // OS would have to crash without updating the state to "offline". const lostRemoteHeartbeat = Date.now() - status.lastHeartbeat > LOST_REMOTE_HEARTBEAT_AFTER; if (lostRemoteHeartbeat) { return true; } return false; } exports.deviceHasLostHeartbeat = deviceHasLostHeartbeat;