@neurosity/sdk
Version:
Neurosity SDK
52 lines (51 loc) • 2.89 kB
JavaScript
;
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;