Skip to content

Interruptible inference-model-updater loop #427

Merged
timmarkhuff merged 19 commits into
mainfrom
refresh-rate-resilience
Jun 18, 2026
Merged

Interruptible inference-model-updater loop #427
timmarkhuff merged 19 commits into
mainfrom
refresh-rate-resilience

Conversation

@timmarkhuff

@timmarkhuff timmarkhuff commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Background

When the inference-model-updater sleeps between update cycles, it does not respond to
ExperimentalApi.edge.set_config calls. If refresh_rate is high, this means adding or
removing detectors can be delayed by the full sleep duration.

Changes

  1. Move get_active_detector_ids() onto DatabaseManager as a class method. The
    module-level function in edge_config_manager.py delegates to it; no callers break.

  2. Replace time.sleep with _wait_for_next_cycle in the model-update loop. Polls
    every 2s and wakes early if set_config added/removed a detector or refresh_rate
    changed. The detector baseline is captured once per cycle (before the per-detector loop)
    and shared with both the mid-cycle check and the wait, so a config change detected
    mid-cycle also causes _wait_for_next_cycle to return immediately rather than sleeping.

  3. Early-exit mid-cycle — the per-detector for-loop checks after each detector and
    breaks early if the config changed, restarting the outer loop immediately.

Notes

Paired with groundlight/python-sdk#439, which enforces a 1-day cap on refresh_rate.

Three related changes to make the inference-model-updater more responsive
to set_config calls and robust against misconfigured refresh_rate values.

1. Move get_active_detector_ids() onto DatabaseManager as a class method.
   The module-level function in edge_config_manager.py now delegates to it,
   keeping all existing callers working unchanged.

2. Add _wait_for_next_cycle(db_manager, wait) to replace the bare
   time.sleep(sleep_duration) in the model-update loop. The function polls
   every 2s and returns early if set_config added or removed a detector
   (detected via get_active_detector_ids / get_pending_deletions). The
   baseline is captured once at entry (edge-triggered) so a permanently-
   failing deployment never causes a busy loop. wait=None means sleep
   indefinitely until a detector change appears, enabling refresh_rate=None.

3. Update the call site to pass wait=None when refresh_rate is None, and
   update configs/edge-config.yaml and CONFIGURING-DETECTORS.md to document
   the new null-to-disable behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
@timmarkhuff timmarkhuff changed the title Interruptible model-updater wait and refresh_rate=None support Interruptible inference-model-updater loop Jun 15, 2026
Comment thread configs/edge-config.yaml
# For configuring detectors on the edge endpoint. See CONFIGURING-DETECTORS.md for more information.

global_config: # These settings affect the overall behavior of the edge endpoint.
refresh_rate: 60 # How often to attempt to fetch updated ML models (in seconds). Defaults to 60.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default is defined by the python-sdk. Better not to include it in a comment here. The comment could become stale.

Comment thread pyproject.toml Outdated
"cachetools>=5.3.1,<6.0.0",
"fastapi>=0.115.0,<0.116.0",
"groundlight>=0.25.0,<0.26.0",
"groundlight>=0.29.0,<0.30.0",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were a bit behind on our python-sdk version

@timmarkhuff timmarkhuff requested a review from honeytung June 16, 2026 18:42

@honeytung honeytung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

timmarkhuff added a commit to groundlight/python-sdk that referenced this pull request Jun 17, 2026
## Changes

- Add `le=86400` to `GlobalConfig.refresh_rate`, capping the maximum
value at 1 day.
Values above this are now rejected at construction time with a clear
`ValidationError`.

## Notes

This PR is paired with groundlight/edge-endpoint#427, which makes the
model-updater
loop more responsive to `set_config` calls. Neither PR depends on the
other for correctness.

---------

Co-authored-by: Tim Huff <thuff@axon.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@timmarkhuff timmarkhuff merged commit 4ab5270 into main Jun 18, 2026
14 checks passed
@timmarkhuff timmarkhuff deleted the refresh-rate-resilience branch June 18, 2026 18:42
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.

2 participants