Repository navigation
Conversation
MaxGhenis
force-pushed
the
fix/telemetry-settled-rejection-local-only
branch
from
October 10, 2026 00:23
d6958da to
0038e99
Compare
MaxGhenis
added a commit
that referenced
this pull request
Oct 10, 2026
Review round 1 on #6: the changelog promised a warning naming the status for a refused registration too, but `_register` passes no message, so the service prints the existing rejected-credential text for any settled registration refusal, as it already did for 409. Only a refused batch's warning names the status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…forever Ports PolicyEngine/microcosm 0e80b0361 (microcosm#1147) into the emitter's copy of the telemetry service, on top of the foreign-run fix (#5). An events answer other than 202, 401 or 403, and a registration answer other than 201, 401, 403 or 409, was retried without end. A collector that answers a batch with 422 (an event shape it does not accept), 404, 413 or 400 therefore wedged that run's queue for good, and the retry delay it set gates every later delivery pass of the service. A 4xx other than a timeout (408) or a rate limit (429) on a run's events now makes the run local-only (`collector_rejected_events`) with one warning that names the status; the same rule covers a rejected registration (`run_registration_rejected`). Both are about the run and not the caller, so a service applies them to a run it has adopted too, without a warning in its own build. 401 still exchanges the token again, 403 is still about the login, and 408, 429 and 5xx still retry. collector.py now equals microcosm#1177's (head 615d84f89, which contains 0e80b0361) apart from the package path. Tests: Microcosm's delivery test, plus the registration side, every 4xx on both requests, a 401 re-exchange, and a contract case against the pinned collector (422 for an event outside its schema, 404 for an unknown run). The foreign-run tests now expect an adopted run refused with 422, at registration or at its events, to go local-only, accept that only when the adopting service's latest answer is that 422 for that run, and check that a refused orphan sets no retry delay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1 on #6: the changelog promised a warning naming the status for a refused registration too, but `_register` passes no message, so the service prints the existing rejected-credential text for any settled registration refusal, as it already did for 409. Only a refused batch's warning names the status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
fix/telemetry-settled-rejection-local-only
branch
from
October 10, 2026 01:54
7ca9e22 to
9d4ee06
Compare
MaxGhenis
added a commit
that referenced
this pull request
Oct 10, 2026
… lost run again Three follow-ups to the settled-rejection rule in the telemetry service's collector delivery, made in step with Microcosm's copy of this code. A refused registration printed the "credential was not accepted as a PolicyEngine organization member" warning, because `_make_local_only` defaulted to it. That was false for a 409 (the owner registering with other metadata), a 422 and any other settled 4xx, and for a 403 on a registration or on events, where the collector had accepted the login and refused it the run. A rejected registration now names its HTTP status, a 403 names the Hugging Face user, and the message no longer has a default. A batch was bounded by count only. A full batch of the largest events (non-ASCII messages, details at their limit) is over the collector's 1 MiB request limit, which it answers with 413 for the whole request, and that made the run local-only. A batch is now the longest run of leading events whose request body fits, measured with the serialization `_http_post` sends. An event too large to send alone is sent alone, for the collector to refuse. A 404 for a run's events means the collector does not have a run this service registered. The service now registers the run again and sends the same batch on the next pass; a second 404 with no batch acknowledged in between makes the run local-only, as before. Stacked on #6 (0038e99). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 19, 2026
This branch has not been deployed
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.
Problem
CollectorDeliveryretried every collector answer it did not recognise:_deliver): 202 acknowledges, 401 drops the collector token, 403 makes the run local-only. Any other status called_defer_retry()._register): 201 registers, 401 drops the token, 403 and 409 make the run local-only. Any other status called_defer_retry().So a collector that answers a batch with 422 (an event shape it does not accept), or with 400, 404 or 413, was sent the same batch again without end, and that run's queue never drained.
_defer_retry()also sets the service's single_next_attempt_at, which gates every laterflush_once, so the wedged run's retry delay held back the service's other runs too.This is the emitter's copy of the bug fixed in Microcosm by PolicyEngine/microcosm@0e80b0361 (part of PolicyEngine/microcosm#1147, merged 2026-10-09). There the trigger was an older collector answering a
blockedevent with 422. The collector pinned by this repo's CI (80a2a4ac) has that same schema: itsstatusliteral has noblocked.Stacked on #5. The base branch is
fix/telemetry-foreign-run-local-only(at093efb1); this PR is retargeted tomainonce #5 merges. It needs #5's_make_local_only(..., caller_dependent=...).Change
src/microcosm_emitter/telemetry/service/collector.pynow equals microcosm#1177's (head615d84f89, which contains 0e80b0361 and #1177's review fixes) apart from the package path. #5 (at093efb1) carries #1177's review fixes, so the only difference between #5's file and this one is the #1147 rule below._permanent_client_error(status): a 4xx other than 408 (timeout) and 429 (rate limit).collector_rejected_events(LOCAL_ONLY_REJECTED_EVENTS) and a warning that names the status (REJECTED_EVENTS_MESSAGE).run_registration_rejected.caller_dependent=False: the answer is about the run, so a service applies it to a run it adopted from another build as well as to its own. Events 403 and registration 403 staycaller_dependent=True, as in Keep one build's telemetry login from deciding other builds' runs #5._make_local_onlytakes the warning text and hands it to_warn_denied. The warning still prints only for the service's own run.README and a
changelog.dfragment describe the rule.How the collector answers (read for this change)
From PolicyEngine/calibration-diagnostics
telemetry-service/telemetry_collector/(app.py,storage.py,models.py) at the pinned80a2a4ac:The new contract test executes the 422 and 404 rows against the real pinned collector in CI's
collectorjob.Invariants
Each is checked by a test named below. Scope is stated per item; none is claimed beyond it.
_permanent_client_erroris true exactly when the status is a 4xx other than 408 and 429. Checked exhaustively (test_only_a_settled_client_error_is_permanent).test_every_client_error_has_one_outcome, exhaustive, fake transport):run_registration_rejectedat registration,collector_authorization_rejectedat events), with one warning.run_registration_rejectedorcollector_rejected_events) with one warning, which for events names the status. Nothing about the run is sent again, even after the retry delay.run_registration_rejectedafter that service received a 409 or a 422 for that run's registration, orcollector_rejected_eventsafter it received a 422 for that run's events. It is never caused by the service's own login. Checked after every step with Keep one build's telemetry login from deciding other builds' runs #5's rule that the deciding service's latest collector answer must be that refusal.run_registration_rejected, and 422 at events givescollector_rejected_events. Before this change a 422 run was expected to stay pending and queued.test_a_refused_orphan_does_not_hold_back_the_adopters_own_run, three cases).test_an_orphan_the_collector_refuses_goes_local_only_without_a_warning_here, three cases).Differential checks.
diffof thiscollector.pyand microcosm#1177's at615d84f89, with the package path substituted, is empty (run locally; Microcosm is not a dependency, so this is not in CI).tests/test_collector_contract.py::test_a_settled_refusal_makes_the_run_local_only_instead_of_retrying(422 and 404), CIcollectorjob only.Tests
tests/telemetry/test_delivery.pytest_a_settled_collector_rejection_goes_local_only_instead_of_retrying, ported, with 413, 400 and 503 added and a check that 408/429/503 are sent again once the delay passes.test_an_expired_collector_token_is_exchanged_again_not_made_local_only: 401 is a 4xx too, so branch order matters.tests/telemetry/test_foreign_runs.pymalformed_run_ids), checked before the owner as the real schema check is.Host.flush(..., advance=False)runs a pass with no time elapsed, for invariant 6.tests/test_collector_contract.py: the contract case above.Verification
d6958daand0038e99. On9d4ee06thecollectorjob passed, which runs the new contract cases (422 for an event outside the schema, 404 for an unknown run, the latter now seeded with the id-pair key) against the real pinned collector; see this PR's checks for the rest.d6958da) asked for changes. Its two blocking findings were Keep one build's telemetry login from deciding other builds' runs #5's later commit07b2c36read as deletions through the moving base branch; the rebase settled them, and the four tests it replayed pass. Its non-blocking findings are fixed: the invariant checks use Keep one build's telemetry login from deciding other builds' runs #5's latest-answer rule, the new delivery tests close their deliveries, the changelog no longer promises a status-naming warning for registration, and the 1 MiB statement below gives measured thresholds.Local, macOS, Python 3.14, at
9d4ee06:test_delivery.py,test_foreign_runs.py,test_module.py): 120 passed (33, 41 and 46).tools/check-quality.shis clean.checks/deep_1500_at_9d4ee06.txt). Each new path was reached: an adopted orphan refused with 422 at registration (9.3% of examples) and at its events (6.7%), and an own run made local-only forcollector_rejected_events(2.2%).mutants/SUMMARY.md). They cover the classifier's bounds and retryable codes, each branch's reason and caller-dependence, the warning text, branch order against 401 and 403, and a settled refusal that also sets a retry delay. The survivor removes_warn_denied's once-only guard, which is equivalent: a run is warned about only as it goes local-only, after which it is never delivered again. Disabling the rule (_permanent_client_erroralways false) fails 16 tests.Limits and follow-ups
Content-Lengthwithout reading the body; whether a client always receives that status was not tested.checks/batch_size_bound.pyin the evidence folder computes these. Such a run now goes local-only where before it wedged; batching by bytes would deliver it. Follow-up for both packages._registerpasses no message, so the own-run warning for 409, and now for any other settled 4xx, is the "credential was not accepted" text. That was already so for 409 here and in Microcosm. Follow-up for both packages.collector.py, this file should follow.axiom: n/a: telemetry infrastructure
🤖 Generated with Claude Code