[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: register comment.
Kind: tracking. Source: review Part 7.2 ("Three retry systems in one module") and R12; register row C15.
Problem
ApiClient has two independent retry policies. A third path, the blob and diff downloads, has none.
| Path |
Policy |
Retryable |
Retry-After |
Jitter |
JSON calls (send_json_request) |
api::retry: 3 retries, a run-wide 60 s window, SOCKET_API_MAX_RETRIES |
429, 503 (retry.rs#L182-L187); #610 adds connect resets |
delta-seconds or HTTP-date (retry.rs#L193-L204) |
seeded SplitMix (retry.rs#L209) |
Vendor service POST/GET and download_artifact (VendorRetryPolicy, vendor_backoff, download_artifact_capped) |
3 attempts, 400 ms → 4 s, no env knob |
429, 500, 502, 503, 504 + transport (client.rs#L327-L329) |
delta-seconds only (retry_after_secs) |
a second jitter_sample() built on RandomState (client.rs#L319-L324) |
Blob and diff (fetch_binary, client.rs#L1066-L1124) |
none |
— |
— |
— |
The same Socket hosts are therefore treated differently depending on the call. Shown by execution on 045d7ec (a temporary unit test, run twice, not committed), with Retry-After: Fri, 27 Mar 2026 19:12:42 GMT:
api::retry::parse_retry_after waits until that date;
- the vendor path's
retry_after_secs returns None and falls back to its own backoff;
- 500, 502 and 504 are retried on vendor calls but are final on JSON calls.
Target design
One retry primitive in api::retry:
- one
Retry-After parser and one jitter source;
- a
Classifier per call family, since the retryable statuses legitimately differ (vendor archives build asynchronously, the patch API throttles);
- one
retry(op, policy, classifier) loop.
VendorRetryPolicy becomes a preset of that policy, not a second implementation, and fetch_binary gets the JSON preset. Timeouts stay where #581 put them (ApiTimeouts).
Checklist (each item one PR, in order)
Out of scope: the non-patch-API stacks (RegistryClient, self-update and telemetry clients). Telemetry's per-event client is C22.
Dependencies
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: register comment.
Kind: tracking. Source: review Part 7.2 ("Three retry systems in one module") and R12; register row C15.
Problem
ApiClienthas two independent retry policies. A third path, the blob and diff downloads, has none.Retry-Aftersend_json_request)api::retry: 3 retries, a run-wide 60 s window,SOCKET_API_MAX_RETRIESretry.rs#L182-L187); #610 adds connect resetsretry.rs#L193-L204)retry.rs#L209)download_artifact(VendorRetryPolicy,vendor_backoff,download_artifact_capped)client.rs#L327-L329)retry_after_secs)jitter_sample()built onRandomState(client.rs#L319-L324)fetch_binary,client.rs#L1066-L1124)The same Socket hosts are therefore treated differently depending on the call. Shown by execution on
045d7ec(a temporary unit test, run twice, not committed), withRetry-After: Fri, 27 Mar 2026 19:12:42 GMT:api::retry::parse_retry_afterwaits until that date;retry_after_secsreturnsNoneand falls back to its own backoff;Target design
One retry primitive in
api::retry:Retry-Afterparser and one jitter source;Classifierper call family, since the retryable statuses legitimately differ (vendor archives build asynchronously, the patch API throttles);retry(op, policy, classifier)loop.VendorRetryPolicybecomes a preset of that policy, not a second implementation, andfetch_binarygets the JSON preset. Timeouts stay where #581 put them (ApiTimeouts).Checklist (each item one PR, in order)
Retry-Afterparser and jitter ontoapi::retry, deletingretry_after_secsandjitter_sample()fromclient.rs.retry_withloop. Replace the three hand-written vendor loops (request_vendor_package,download_vendor_archive_retrying/vendor_download_retryanddownload_artifact_capped) andsend_json_request's loop, keeping each call family's classifier. Not filed yet; it needs child 1 and Retry patch API connections reset mid-handshake #610.fetch_binary) under the JSON preset. Not filed yet; it is blocked by Stream patch blob and diff downloads to disk (#571) #607 (C37), which rewritesfetch_binaryto stream.download_vendor_archive_onceanddownload_artifact_capped_once. Not filed yet.Out of scope: the non-patch-API stacks (
RegistryClient, self-update and telemetry clients). Telemetry's per-event client is C22.Dependencies
ApiClient).