Skip to content

Support fallback NTP servers for edge time sync (#79)#82

Open
ff225 wants to merge 1 commit into
mainfrom
fix/sciot-079-ntp-fallback-servers
Open

Support fallback NTP servers for edge time sync (#79)#82
ff225 wants to merge 1 commit into
mainfrom
fix/sciot-079-ntp-fallback-servers

Conversation

@ff225

@ff225 ff225 commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

A remote NTP server (the public pool configured in settings.yaml) can carry more time-synchronization error than a server on the local network. This adds support for an ordered list of fallback NTP servers per transport, so a local server can be configured as primary with the existing remote pool kept as a fallback (or vice versa) -- reducing the chance that transient unreachability of one server degrades sync quality or forces a fall back to offset=0.0.

Changes

  • New server.communication.ntp_sync module: shared sync_with_ntp_fallback (startup, retries every server each round with exponential backoff) and resync_ntp_fallback (periodic re-sync, tries each server once) helpers, extracted from the three near-identical implementations in http_server.py, websocket_server.py, and mqtt_client.py.
  • All three transports accept an optional ntp_fallback_servers: list[str] constructor arg and try [ntp_server, *ntp_fallback_servers] in order instead of only the single configured server.
  • src/sciot/config.py: new optional communication.{http,websocket,mqtt}.ntp_fallback_servers config key (list of non-empty strings), validated via a new _optional_string_list helper.
  • src/server/edge/run_edge.py: wires the new config key through to each transport constructor.
  • src/server/settings.yaml: documents the new key with a commented-out example under each transport's ntp_server.

Backwards compatible: the new parameter defaults to None/[] everywhere, so existing configs without ntp_fallback_servers behave exactly as before (single server, same retry/backoff schedule).

Test plan

  • New tests/unit/test_ntp_sync.py: primary-server success, fallback on primary failure, all-servers-unreachable (0.0 offset), and periodic resync variants -- all with a mocked ntplib.NTPClient and mocked sleep, no real network.
  • tests/unit/test_config_validation.py: new cases for invalid ntp_fallback_servers (wrong type / empty string) on each transport, and a valid-list acceptance test.
  • Fast CI suite: uv run pytest tests/unit tests/integration/test_client_resilience.py tests/integration/test_client_lifecycle.py tests/integration/test_variance_and_local_inference.py tests/test_mqtt_client tests/test_offloading_algo -- 223 passed, 1 skipped.
  • ruff check on all changed files -- clean.

Closes #79

A single remote NTP server (e.g. the public pool) can introduce
synchronization errors that hurt telemetry accuracy. All three
transports (http, websocket, mqtt) now try an optional ordered list
of fallback servers -- e.g. a local NTP server first -- before giving
up on sync, sharing the retry/backoff logic via a new
server.communication.ntp_sync module.

Closes #79
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Local NTP server

1 participant