@ruanitto/react-native-ntp-sync
Version:
Sync time using NTP servers
163 lines (162 loc) • 6.75 kB
JavaScript
"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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NtpClientError = void 0;
const error_1 = require("./internals/error");
Object.defineProperty(exports, "NtpClientError", { enumerable: true, get: function () { return error_1.NtpClientError; } });
const client_1 = require("./internals/client");
const default_config_1 = __importDefault(require("./internals/default-config"));
class NTPSync {
constructor(config) {
this.currentIndex = 0;
this.tickId = null;
this.listeners = new Set();
this.computeAndUpdate = (ntpDate) => {
const tempServerTime = ntpDate.getTime();
const tempLocalTime = Date.now();
const dt = tempServerTime - tempLocalTime;
if (this.historyDetails.deltas.length === this.limit) {
this.historyDetails.deltas.shift();
}
this.historyDetails.deltas.push({
dt: dt,
ntp: tempServerTime,
});
this.historyDetails.lastSyncTime = tempLocalTime;
this.historyDetails.lastNtpTime = tempServerTime;
return dt;
};
this.getDelta = () => __awaiter(this, void 0, void 0, function* () {
if (this.isOnline) {
const fetchingServer = Object.assign({}, this.historyDetails.currentServer);
try {
const ntpDate = yield client_1.getNetworkTime(this.historyDetails.currentServer.server, this.historyDetails.currentServer.port, this.syncTimeout);
const delta = this.computeAndUpdate(ntpDate);
return {
delta,
fetchingServer,
};
}
catch (err) {
this.shiftServer();
throw new error_1.NtpClientError(err, fetchingServer);
}
}
else {
return { delta: 0 };
}
});
this.getHistory = () => {
return JSON.parse(JSON.stringify(this.historyDetails));
};
this.getTime = () => {
const sum = this.historyDetails.deltas.reduce((a, b) => {
return a + b.dt;
}, 0);
const avg = Math.round(sum / this.historyDetails.deltas.length) || 0;
return Date.now() + avg;
};
this.shiftServer = () => {
if (this.ntpServers.length > 1) {
this.currentIndex++;
this.currentIndex %= this.ntpServers.length;
}
this.historyDetails.currentServer = this.ntpServers[this.currentIndex];
};
this.startAutoSync = () => {
if (!this.tickId) {
this.tickId = setInterval(() => this.syncTime(), this.tickRate);
}
};
this.stopAutoSync = () => {
if (this.tickId) {
clearInterval(this.tickId);
this.tickId = null;
}
};
this.syncTime = () => __awaiter(this, void 0, void 0, function* () {
if (this.isOnline) {
try {
const delta = yield this.getDelta();
this.historyDetails.currentConsecutiveErrorCount = 0;
this.historyDetails.isInErrorState = false;
this.listeners.forEach((handler) => handler(this.getHistory()));
return true;
}
catch (err) {
const ed = {
name: err.name,
message: err.message,
server: err.server,
stack: err.stack,
time: Date.now(),
};
this.historyDetails.currentConsecutiveErrorCount++;
if (this.historyDetails.errors.length === this.limit) {
this.historyDetails.errors.shift();
}
this.historyDetails.errors.push(ed);
this.historyDetails.isInErrorState = true;
this.historyDetails.lastError = ed;
this.historyDetails.lifetimeErrorCount++;
this.historyDetails.maxConsecutiveErrorCount = Math.max(this.historyDetails.maxConsecutiveErrorCount, this.historyDetails.currentConsecutiveErrorCount);
}
return false;
}
return false;
});
this.config = Object.assign(default_config_1.default, config);
this.ntpServers = this.config.servers;
this.limit = this.config.history;
this.tickRate = this.config.syncInterval;
this.syncTimeout = this.config.syncTimeout;
this.historyDetails = {
currentConsecutiveErrorCount: 0,
currentServer: this.ntpServers[this.currentIndex],
deltas: [],
errors: [],
isInErrorState: false,
lastSyncTime: null,
lastNtpTime: null,
lastError: null,
lifetimeErrorCount: 0,
maxConsecutiveErrorCount: 0,
};
this.isOnline = this.config.startOnline;
if (this.config.syncOnCreation && this.config.startOnline) {
this.syncTime();
}
if (this.config.autoSync) {
this.startAutoSync();
}
}
setIsOnline(isOnline) {
if (isOnline && !this.isOnline) {
this.isOnline = true;
this.syncTime();
this.startAutoSync();
}
else if (!isOnline && this.isOnline) {
this.stopAutoSync();
this.isOnline = false;
}
}
getIsOnline() {
return this.isOnline;
}
addListener(listener) {
this.listeners.add(listener);
}
}
exports.default = NTPSync;