Refactor and code designing

This commit is contained in:
2026-03-02 03:30:22 +01:00
parent 6d7465ff18
commit e231f4ed05
80 changed files with 6690 additions and 4670 deletions

View File

@@ -1,45 +1,94 @@
import { Injectable, signal, computed } from '@angular/core';
/** Default timeout (ms) for the NTP-style HTTP sync request. */
const DEFAULT_SYNC_TIMEOUT_MS = 5000;
/**
* Maintains a clock-offset between the local system time and the
* remote signaling server.
*
* The offset is estimated using a simple NTP-style round-trip
* measurement and is stored as a reactive Angular signal so that
* any dependent computed value auto-updates when a new sync occurs.
*/
@Injectable({ providedIn: 'root' })
export class TimeSyncService {
// serverTime - clientTime offset (milliseconds)
/**
* Internal offset signal:
* `serverTime = Date.now() + offset`.
*/
private readonly _offset = signal<number>(0);
private _lastSyncAt = 0;
/** Epoch timestamp of the most recent successful sync. */
private lastSyncTimestamp = 0;
/** Reactive read-only offset (milliseconds). */
readonly offset = computed(() => this._offset());
// Returns a server-adjusted now() using the current offset
/**
* Return a server-adjusted "now" timestamp.
*
* @returns Epoch milliseconds aligned to the server clock.
*/
now(): number {
return Date.now() + this._offset();
}
// Set offset based on a serverTime observed at approximately receiveAt
setFromServerTime(serverTime: number, receiveAt?: number): void {
const observedAt = receiveAt ?? Date.now();
const offset = serverTime - observedAt;
this._offset.set(offset);
this._lastSyncAt = Date.now();
/**
* Set the offset from a known server timestamp.
*
* @param serverTime - Epoch timestamp reported by the server.
* @param receiveTimestamp - Local epoch timestamp when the server time was
* observed. Defaults to `Date.now()` if omitted.
*/
setFromServerTime(serverTime: number, receiveTimestamp?: number): void {
const observedAt = receiveTimestamp ?? Date.now();
this._offset.set(serverTime - observedAt);
this.lastSyncTimestamp = Date.now();
}
// Perform an HTTP-based sync using a simple NTP-style roundtrip
async syncWithEndpoint(baseApiUrl: string, timeoutMs = 5000): Promise<void> {
/**
* Perform an HTTP-based clock synchronisation using a simple
* NTP-style round-trip.
*
* 1. Record `clientSendTime` (`t0`).
* 2. Fetch `GET {baseApiUrl}/time`.
* 3. Record `clientReceiveTime` (`t2`).
* 4. Estimate one-way latency as `(t2 t0) / 2`.
* 5. Compute offset: `serverNow midpoint(t0, t2)`.
*
* Any network or parsing error is silently ignored so that the
* last known offset (or zero) is retained.
*
* @param baseApiUrl - API base URL (e.g. `http://host:3001/api`).
* @param timeoutMs - Maximum time to wait for the response.
*/
async syncWithEndpoint(
baseApiUrl: string,
timeoutMs: number = DEFAULT_SYNC_TIMEOUT_MS,
): Promise<void> {
try {
const controller = new AbortController();
const t0 = Date.now();
const clientSendTime = Date.now();
const timer = setTimeout(() => controller.abort(), timeoutMs);
const resp = await fetch(`${baseApiUrl}/time`, { signal: controller.signal });
const t2 = Date.now();
const response = await fetch(`${baseApiUrl}/time`, {
signal: controller.signal,
});
const clientReceiveTime = Date.now();
clearTimeout(timer);
if (!resp.ok) return;
const data = await resp.json();
// Estimate one-way latency and offset
if (!response.ok) return;
const data = await response.json();
const serverNow = Number(data?.now) || Date.now();
const midpoint = (t0 + t2) / 2;
const offset = serverNow - midpoint;
this._offset.set(offset);
this._lastSyncAt = Date.now();
const midpoint = (clientSendTime + clientReceiveTime) / 2;
this._offset.set(serverNow - midpoint);
this.lastSyncTimestamp = Date.now();
} catch {
// ignore sync failures; retain last offset
// Sync failure is non-fatal; retain the previous offset.
}
}
}