SEP-1734: Pass the previous snapshot to RefreshCallback so rebind callbacks can act on what changed - #1298
SEP-1734: Pass the previous snapshot to RefreshCallback so rebind callbacks can act on what changed#1298peter-o-addo wants to merge 8 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the settings-override lifecycle so rebind callbacks receive both the previous and current override snapshots (via a new SnapshotChange payload), enabling callbacks to react to what specifically changed (e.g., evicting clients keyed to an old endpoint after an override update/delete).
Changes:
- Introduces
SnapshotChangeand updates the core override lifecycle callback signature to deliver previous + current snapshots. - Updates SEP and Tasks rebind callbacks to accept the new payload and to evict cached clients for both prior and new endpoints where appropriate.
- Expands/updates tests to cover the new callback payload and endpoint create/change/delete eviction paths, and adds a changelog fragment.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| app/core/settings_override/lifecycle.py | Adds SnapshotChange and updates RefreshCallback/fire_change_callbacks to deliver previous + current snapshots. |
| app/core/settings_override/init.py | Re-exports SnapshotChange from the settings override package. |
| app/sep/main.py | Updates endpoint rebind logic to accept SnapshotChange and evict previous/current endpoints when using registry-cached clients. |
| app/sep/settings_override.py | Updates PMM client invalidation callback to evict on previous/current endpoints using SnapshotChange. |
| app/tasks/main.py | Updates the Nomad rebind callback signature to accept SnapshotChange. |
| tests/app/sep/test_override_callbacks.py | Adds coverage for endpoint and PMM create/change/delete eviction behavior using SnapshotChange. |
| tests/app/tasks/test_main.py | Updates Tasks tests to pass SnapshotChange to the Nomad rebind callback. |
| tests/app/core/settings_override/test_worker.py | Updates worker refresher callback test helper signature to SnapshotChange. |
| tests/app/core/settings_override/test_lifecycle.py | Adds a test asserting fire_change_callbacks delivers a SnapshotChange (including delete semantics). |
| changelog.d/SEP-1734.fixed.md | Documents the runtime-override eviction behavior change for endpoint-based clients. |
| assert old._session is None # the previous client was drained | ||
| finally: | ||
| invalidate.assert_not_awaited() | ||
| await new.close() | ||
| finally: | ||
| sep_settings._set_snapshot({}) |
1. Inventory endpoint — HTTP responsesBaselineGET /api/sep/admin/settings/SEPSettings/INVENTORY_ENDPOINT```
```json
{
"setting_class": "SEPSettings",
"key": "INVENTORY_ENDPOINT",
"value": "http://localhost:8000/api/inventory",
"has_override": false,
"reload": "hot"
}Create — HTTP 200PATCH /api/sep/admin/settings/SEPSettingsContent-Type: application/json
{"INVENTORY_ENDPOINT":"https://inv-a.example.org"}[
{
"setting_class": "SEPSettings",
"key": "INVENTORY_ENDPOINT",
"value": "https://inv-a.example.org/",
"has_override": true,
"reload": "hot"
}
]Change — HTTP 200PATCH /api/sep/admin/settings/SEPSettingsContent-Type: application/json
{"INVENTORY_ENDPOINT":"https://inv-b.example.org"}{
"setting_class": "SEPSettings",
"key": "INVENTORY_ENDPOINT",
"value": "https://inv-b.example.org/",
"has_override": true
}Delete — HTTP 204, then GET after deleteDELETE /api/sep/admin/settings/SEPSettings/INVENTORY_ENDPOINT→ HTTP 204GET /api/sep/admin/settings/SEPSettings/INVENTORY_ENDPOINT```
```json
{
"setting_class": "SEPSettings",
"key": "INVENTORY_ENDPOINT",
"value": "http://localhost:8000/api/inventory",
"has_override": false
}Result: PASS — create / change / delete all applied; value restored to base. 2. Tasks endpoint — HTTP responsesCreate — HTTP 200PATCH /api/sep/admin/settings/SEPSettings
{"TASKS_ENDPOINT":"https://tasks-a.example.org"}{
"setting_class": "SEPSettings",
"key": "TASKS_ENDPOINT",
"value": "https://tasks-a.example.org/",
"has_override": true
}Change — HTTP 200{
"setting_class": "SEPSettings",
"key": "TASKS_ENDPOINT",
"value": "https://tasks-b.example.org/",
"has_override": true
}Delete — HTTP 204, then GETDELETE /api/sep/admin/settings/SEPSettings/TASKS_ENDPOINT → HTTP 204{
"setting_class": "SEPSettings",
"key": "TASKS_ENDPOINT",
"value": "http://localhost:8000/api/tasks",
"has_override": false
}Result: PASS. 3. PMM endpoint — HTTP responsesBaseline{
"setting_class": "Settings",
"key": "PMM",
"value": {
"endpoint": "https://127.0.0.1:9090",
"api_key": "**********",
"verify_ssl": false
},
"has_override": false
}Create — HTTP 200PATCH /api/sep/admin/settings/Settings
{"PMM__endpoint":"https://pmm-a.example.org"}{
"setting_class": "Settings",
"key": "PMM",
"value": {
"endpoint": "https://pmm-a.example.org",
"api_key": "**********",
"verify_ssl": false
},
"has_override": true
}Change — HTTP 200{
"value": {
"endpoint": "https://pmm-b.example.org",
"api_key": "**********",
"verify_ssl": false
},
"has_override": true
}Same-endpoint credential change — HTTP 200PATCH /api/sep/admin/settings/Settings
{"PMM__api_key":"test-key-for-rebind"}{
"value": {
"endpoint": "https://pmm-b.example.org",
"api_key": "**********",
"verify_ssl": false
},
"has_override": true
}Endpoint unchanged; only credential override applied. Delete — HTTP 204 × 2, then GETDELETE /api/sep/admin/settings/Settings/PMM__api_key → HTTP 204
DELETE /api/sep/admin/settings/Settings/PMM__endpoint → HTTP 204{
"value": {
"endpoint": "https://127.0.0.1:9090",
"api_key": "**********",
"verify_ssl": false
},
"has_override": false
}Result: PASS. |
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@copilot resolve the merge conflicts in this pull request |
# Conflicts: # app/core/settings_override/lifecycle.py Co-authored-by: yyyyyyyan <24644216+yyyyyyyan@users.noreply.github.com>
Co-authored-by: yyyyyyyan <24644216+yyyyyyyan@users.noreply.github.com>
Resolved the merge conflict in |
Summary
Pass both override snapshots into rebind callbacks so endpoint changes can evict clients left on the old origin.
lifecycle.py,__init__.py: addSnapshotChangeand deliver previous + current to every rebind callbacksettings_override.py,main.py(SEP): evict previous and current PMM / Inventory / Tasks endpoints on override create, change, and deletemain.py(tasks): accept the new change payload in the Nomad rebind callbackSEP-1734.fixed.md: note that a replaced endpoint no longer leaves a stale client until shutdownTested
Checklist
make test)make run-pre-commit)make makemigrations)changelog.d/if the change is user-facing (make changelog-add), or confirmed N/A (internal-only change, or a same-release-cycle fix for an unreleased sibling ticket)