test(horismos,archon): config completeness + E2E SIGHUP regression; fix(archon,ergasia): reload deadlock + DHT isolation (#529 step 9)#589
Merged
Conversation
…P reload regression + docs; fix(ergasia): instance-local DHT persistence (#529) Gate-Passed: kanon 0.1.5 +stages:fmt,check,clippy,nextest,lint sha:c106f795d08319830730f9130a562cc6cdd86937
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 9 — the final step of the #529 reactive-config migration. Makes the config classification self-enforcing, proves the whole SIGHUP path end-to-end, and documents it. Building the E2E test surfaced two real bugs (below), both fixed here.
Completeness classification test (
crates/horismos/src/diff.rs): walks every serde-json leaf of a fully-populated exemplarConfig(eachOption<Struct>subsystem set toSome(..)so mixed subtrees expose per-field leaves;taxis.libraries.<id>.*canonicalized). Asserts every leaf is in exactly one of three lists —LIVE(66 leaves, the reactive contract wired by steps 2-8),RESTART_REQUIRED(10 leaves), orUNWIRED(31 dead-config leaves, each// #575-commented) — and that their union is exactly the full 107-leaf set (disjoint + exhaustive, no ghosts either direction). Adding a config field without classifying it now fails the build.E2E SIGHUP regression (
crates/archon/tests/config_reload_e2e.rs): spawns the realharmoniabinary, parses the first-run admin password from stdout, logs in, rewrites the TOML (opds_page_sizeLIVE,jwt_secretrotation,db_pathRESTART), sendsSIGHUP, then bounded-polls (no fixed sleeps) to assert the page-size change is live, the pre-rotation bearer now 401s while a refresh recovers, andrestart_pendingcontainsdatabase.db_path. The child is reaped in aDropguard.Two production bugs the E2E test caught and this PR fixes:
archon/src/main.rs) —mainheld aStdoutLockguard across the entirerun_servelifetime (its future never migrates threads undertokio::main), so the first concurrenttracing::call (the SIGHUP handler) blocked forever on the same lock. Fixed by passing an unlockedStdouthandle (locks per write, never across an await). Without this, every prior step's reload machinery would have hung on the first reload.crates/ergasia/src/session.rs) — librqbit's persistent DHT defaulted to the global~/.cache/com.rqbit.dht/dht.json, so concurrent instances (and parallel test processes) raced/corrupted each other's DHT routing state. Now pinned to an instance-local path undersession_state_pathviaPersistentDhtConfig.config_filename— isolating tests and preventing two harmonia instances on one box from clobbering each other's DHT state.Docs: new
docs/architecture/config-reload.md(mechanism + per-field live/restart table + JWT-rotation / dual-endpoint-drain / rebuild-reset semantics, grounded against shipped code); corrected two now-false claims inconfiguration.md. CHANGELOG is release-please-managed.Gate:
kanon gate --fullgreen — fmt, check, clippy (-D warnings), nextest (full workspace), deny, kanon lint (0/0).Gate-Passedstamped.Closes #529