review classifier: recover from a stored record it can't decode
The controller keeps the classifier's newest runs as one JSON array and its settings as one JSON object, each under one KV key. A document this build could not decode, as after a rollback past a build that added an outcome or a settings field, failed every read and every write until someone deleted the key by hand. A classifier newer than its controller refused every run request for the missing `model`. The run store now decodes the array one record at a time: a record that does not decode is dropped with a WARN naming the bucket, key, index and error, and a document that is not an array reads as no runs. Listing keeps working, and the next recorded run writes back only the records that decoded. The stored settings ignore a field this build does not know; one that still does not decode reads as the defaults with a WARN. The PUT body keeps `deny_unknown_fields`. A PUT now always writes, so a PUT of the defaults also replaces an undecodable document. A run request without `model` runs on haiku, the swarm-wide setting's default, now one constant in swarm-queue-client. `schedules::read` gains a sibling, `read_with`, taking the decoder. Closes #5162
This commit is contained in:
parent
30d9e1d8e6
commit
6f0a72b246
5 changed files with 208 additions and 17 deletions
|
|
@ -135,7 +135,9 @@ The model, the effort and how many requested reviews run at once are one
|
|||
document for the whole swarm. `swarm-controller` keeps it in its
|
||||
`review-classifier-settings` KV bucket under the key `all`, and no other
|
||||
service reads it. With no document stored, the classifier runs on `haiku` at
|
||||
claude's default effort, two reviews at a time.
|
||||
claude's default effort, two reviews at a time. The controller
|
||||
ignores a stored field it doesn't know, and a document it still can't decode
|
||||
counts as none, with a warning in its log, until the next PUT replaces it.
|
||||
|
||||
`GET /api/review-classifier/settings` answers the settings in force.
|
||||
`PUT /api/review-classifier/settings` replaces them whole and answers what it
|
||||
|
|
@ -155,7 +157,8 @@ stored. Both take and give one shape:
|
|||
The controller reads the settings for every run and sends the model and
|
||||
effort in the run request, so a change applies from the next run with no
|
||||
restart. A try-out reads them when it's posted, a review when it gets its
|
||||
place. Lowering the limit lets the runs already going finish.
|
||||
place. Lowering the limit lets the runs already going finish. A run request
|
||||
with no model runs on `haiku`.
|
||||
|
||||
The PUT needs the `Remote-User` header the gateway sets, as the try-out POST
|
||||
does. Every error is problem+json with the reason in `detail`:
|
||||
|
|
@ -387,7 +390,10 @@ The newest 100 runs are one JSON array under the key `recent` in the
|
|||
controller reads or writes. The controller creates the bucket on first use and
|
||||
adds each run with a compare-and-set write, so the list survives a controller
|
||||
restart or a move to another host. Recording the 101st run drops the oldest;
|
||||
there's no time-based retention. The controller logs a failed write, and it
|
||||
there's no time-based retention. The controller leaves a run it can't decode, such
|
||||
as one a newer build recorded, out of the list with a warning in its log, and
|
||||
the next recorded run writes the list back without it; a document that isn't a
|
||||
list reads as no runs. The controller logs a failed write, and it
|
||||
changes nothing on the forge.
|
||||
|
||||
`GET /api/review-classifier/runs` returns the list, newest first. Like the
|
||||
|
|
|
|||
Loading…
Reference in a new issue