Skip to content

Tempo Plugin

@magmacomputing/tempo-plugin-ntp ​

npm version npm peer dependency version License TypeScript Ready

A lightweight, high-precision Community plugin for the Tempo ecosystem that provides client-server network time synchronization and monotonic clock drift compensation using Cristian's algorithm, HTTP Server-Timing headers, jitter rejection, and Exponential Moving Average (EMA) smoothing.


Key Features ​

  • Cristian's Algorithm: Computes client clock offset from round-trip time (Δ = T_server - (T_client + RTT / 2)) without altering the OS clock.
  • Sub-Millisecond Headers: Reads Server-Timing: clock=... with automatic fallback to the standard HTTP Date header.
  • Jitter Rejection & EMA Smoothing: Discards high-latency samples and smooths drift with an Exponential Moving Average.
  • Passive Calibration: Optionally intercepts fetch responses from trusted origins to calibrate with zero extra requests.
  • Synchronous Calibrated Time: Tempo.ntp.now() returns true server-aligned time with no await.
  • Universal HTTP Baseline: Runs identically in browsers, Node.js, Bun, Deno, and Cloudflare Workers.

Installation ​

bash
npm install @magmacomputing/tempo-plugin-ntp

Quickstart ​

Interactive Demo (@magmacomputing/tempo-plugin-ntp)
Open in Full REPL↗
// 🌐 Network Time Sync & Drift Calibration (@magmacomputing/tempo-plugin-ntp)
const { NtpPlugin } = await import('@magmacomputing/tempo-plugin-ntp');
Tempo.use(NtpPlugin);

console.log('Calibrating clock with remote time source...');
const sample = await Tempo.ntp.sync('https://worldtimeapi.org/api/timezone/Etc/UTC');

console.log('Sync Result: Offset', sample.offsetMs, 'ms (Uncertainty: ±' + sample.uncertaintyMs + 'ms, Samples: ' + sample.sampleCount + ')');
console.log('Calibrated Tempo:', Tempo.ntp.now().format('{yyyy}-{mm}-{dd} {hh}:{mi}:{ss}.{ms}'));

return `Calibrated! Offset: ${Tempo.ntp.offset}ms | Local: ${new Tempo().format('{hh}:{mi}:{ss}.{ms}')} vs NTP: ${Tempo.ntp.now().format('{hh}:{mi}:{ss}.{ms}')}`;
Executes 100% in browser via native ESM sandbox
typescript
import { Tempo } from '@magmacomputing/tempo';
import { NtpPlugin } from '@magmacomputing/tempo-plugin-ntp';

// 1. Install the plugin with target server endpoint
Tempo.use(NtpPlugin, {
  server: '/api/time',                                 // Default time synchronization endpoint
  syncInterval: '15m',                                 // Automatic periodic re-sync
  interceptFetch: ['https://api.mycorp.com', '/api/']  // Passively calibrate only on trusted endpoints
});

// 2. Perform an initial sync
await Tempo.ntp.sync();

// 3. Query true calibrated atomic time (100% synchronous!)
const atomicNow = Tempo.ntp.now();
console.log(`True UTC Time: ${atomicNow.format('{yyyy}-{mm}-{dd} {hh}:{mi}:{ss}.{ms}')}`);
console.log(`Measured Drift Offset: ${Tempo.ntp.offset}ms`);
console.log(`Uncertainty Window: ±${Tempo.ntp.drift.uncertaintyMs}ms`);

Configuration Options (NtpSyncOptions) ​

OptionTypeDefaultDescription
serverstringundefinedDedicated HTTP time endpoint returning Date or Server-Timing: clock=<epochMs>.
syncIntervalstring | numberundefinedPeriodic re-sync interval (e.g. '15m', '1h', or ms).
interceptFetchboolean | string | string[] | RegExp | FunctionfalsePassively sniff headers from application fetch calls. Can be true (sniff all), a path prefix, origin array, regex, or predicate.
trustedOriginsstring | string[] | RegExp | FunctionundefinedWhitelist of allowed origins or URL prefixes to sample when interceptFetch: true is enabled.
maxAcceptableRttMsnumber1000Maximum round-trip time threshold in milliseconds. Jittery or delayed requests are discarded.
alphanumber0.3Exponential Moving Average (EMA) smoothing factor between 0.0 and 1.0.

Auto-Installation (Side-Effect Import) ​

typescript
import { Tempo } from '@magmacomputing/tempo';
import '@magmacomputing/tempo-plugin-ntp/install';

// Synchronize and query true calibrated server time
await Tempo.ntp.sync();
const now = Tempo.ntp.now();

API Reference ​

Tempo.ntp.now(timeZone?: string): Tempo ​

Synchronously returns a new Tempo instance anchored to the calibrated atomic server timestamp.

Tempo.ntp.sync(endpoint?: string): Promise<ClockDriftState> ​

Asynchronously sends a lightweight HTTP request to measure Round-Trip Time (RTT) and updates the Exponential Moving Average (EMA) drift offset.

Tempo.ntp.offset: number ​

Getter returning the current clock drift offset in milliseconds (serverTime = localTime + offset).

Tempo.ntp.drift: ClockDriftState ​

Getter returning the full telemetry state snapshot:

typescript
interface ClockDriftState {
  readonly offsetMs: number;
  readonly uncertaintyMs: number;
  readonly lastSyncedAt: number;
  readonly sampleCount: number;
}

Tempo.ntp.isCalibrated: boolean ​

Getter indicating whether at least one valid synchronization sample has been successfully processed.

Tempo.ntp.reset(): void ​

Resets the calibration state and sample count back to zero.

tempo.toNtpTime(): Tempo ​

Instance method that returns a new Tempo instance offset by the current NTP clock drift.


Topic Guides ​


License ​

This is a Community plugin. It is completely free and open-source for personal and commercial use under the MIT license.

Released under the MIT License.