Repository navigation
fix(server): cool down recently failed similarity verification jobs - #3002
Merged
marcocastignoli merged 6 commits intoNov 10, 2026
Merged
marcocastignoli merged 6 commits into
marcocastignoli merged 6 commits into
Conversation
Contributor
Author
|
Quick follow-up, @manuelwedler. Could you take a look at the failed similarity-job cooldown when you have a chance? Thanks. |
marcocastignoli
self-requested a review
November 9, 2026 08:34
…er Solar - Add solarRepoPath to the new unit test service, required since argotorg#3050 - Always reject a found failure; report at least 1 s in Retry-After - Drop the constructor validation that other options do not have - Add a release TODO for the repo.sourcify.dev 429 handling Co-Authored-By: Claude Opus 5.5 <[email protected]>
- The first request calls getBytecode itself, not a middleware - Link sourcifyeth/repo.sourcify.dev#112 in the release TODO Co-Authored-By: Claude Opus 5.5 <[email protected]>
Member
|
The repo.sourcify.dev change for the new Posted with Claude Code |
marcocastignoli
added a commit
to sourcifyeth/repo.sourcify.dev
that referenced
this pull request
Nov 9, 2026
…ed (#112) - The server answers 429 similarity_recently_failed during its cooldown (argotorg/sourcify#3002) - Show the failed state with the minutes left from Retry-After, instead of polling for 5 minutes - Keep polling for duplicate_verification_request Co-authored-by: Claude Opus 5.5 <[email protected]>
- sourcifyeth/repo.sourcify.dev#112 is in production (release argotorg#113) Co-Authored-By: Claude Opus 5.5 <[email protected]>
marcocastignoli
approved these changes
Nov 10, 2026
marcocastignoli
left a comment
Member
There was a problem hiding this comment.
Looks good, thanks! The cooldown check runs before the bytecode fetch and the job insert, and only no_similar_match_found starts it. The repo.sourcify.dev side is live (sourcifyeth/repo.sourcify.dev#112).
Posted with Claude Code
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.
Summary
After a similarity verification job finishes with
no_similar_match_found, an immediate request for the same chain and address currently starts another job and repeats the bytecode fetch and similarity search. This PR adds a configurable cooldown before that work starts and returns429,similarity_recently_failedand the remaining wait inRetry-After.Fixes #2939.
Why
Trigger and root cause
The contract page's automatic similarity request can be repeated by refreshing an unverified contract. The existing
checkIfJobIsAlreadyRunningmiddleware only rejects incomplete jobs. Once a failed job has acompleted_atvalue, another request passes that guard, andverifyFromSimilarityViaWorkerimmediately fetches the runtime bytecode and inserts another job. The background path then searches the same candidate set and, when candidates exist, recompiles them again.The failure classification, completion timestamp, chain, address and verification endpoint are already persisted in
verification_jobs; they were not consulted before another similarity attempt. This implements the existing request in #2939. I reproduced the behaviour onstagingat45acd3358358cc815d1cb6e9868c3b19704fbe99(1 October 2026), rather than assuming it still existed from the issue description. That establishes the affected current revision; it does not identify the original introducing commit.Reproduction and observed behaviour
Both regressions use the actual Express endpoint, the committed database schema and a locally deployed Hardhat contract:
POST /v2/verify/similarity/:chainId/:addressand wait for the job to complete withno_similar_match_found.One regression uses an empty candidate database. The other stores the existing Storage compilation and deploys a contract with the same indexed prefix but a changed
SLOADslot after that prefix. The real worker recompiles the candidate, finds neither a creation nor a runtime match, and persists the no-match outcome. The worker hook only controls when the real worker runs; its result is not stubbed.202, completed no-match job202, another verification job429,similarity_recently_failedRetry-AfterThe empty-candidate regression failed consistently in separate runs against the pristine base. Both regression cases also failed together on that base with
expected 202 to equal 429; both pass with the patch.Impact
Repeated completed failures can consume RPC, database and compilation work even while the deployment and available candidates remain unchanged. The reproduced defect is redundant verification work. I have not measured production traffic, resource exhaustion or a security severity, and this PR makes no such claim.
Changes
no_similar_match_foundfor the same chain and binary contract address, within the configured interval. The existing chain/address index supports this lookup; no schema migration is required.getBytecode, job insertion and background work. Persisted history is shared by replicas using the same database and survives a server restart.similarityFailureCooldownSecondsto the service options and server config:600by default,0to disable. Invalid negative or non-finite values are rejected at construction.Retry-Afterheader, expose that header to cross-origin browser clients, and document the response and configuration in the existing OpenAPI and server README formats.Notes
Validation evidence
The three focused suites passed with 38 tests, including 13 added cases: the two HTTP regressions; completion-time and remaining-header behaviour with a lowercase address; exact expiry; three transient-error controls; endpoint, chain and address isolation; custom duration; disabled cooldown; and expiry during the history lookup. Existing successful verification, duplicate-request, already-verified, storage and worker-error tests in those suites also passed.
The suite selection was:
cd services/server npx mocha --exit \ test/integration/apiv2/verification/verify.similarity.spec.ts \ test/integration/storageServices/SourcifyDatabaseService.spec.ts \ test/unit/VerificationService.spec.tsThe regression-only selection was run against a separate pristine checkout of the base revision with the new tests copied in. It produced two expected assertion failures, not setup or database errors:
npx mocha --exit test/integration/apiv2/verification/verify.similarity.spec.ts \ --grep 'immediate retry after a completed|real candidate recompilation'Dependency package builds (
compilers-types,bytecode-utils,compilers,lib-sourcify) and the server build passed.tsc --noEmit --project services/server/tsconfig.lint.json, Prettier on every changed file, andgit diff --checkpassed. ESLint over the server source and changed tests passed with zero errors and 15 existing unused-variable warnings; unrelated warnings were left alone.The local test environment used Node 24.19.0, Hardhat 3.16.0 and PostgreSQL 18.3 compiled to WASM through PGlite 0.5.8 and its TCP socket adapter. The wrapper loaded the committed schema (including
pg_trgmandpgcrypto) and ran the repository's unchanged fixtures and SQL throughpg. Native PostgreSQL could not start in this sandbox, so the suite commands above were launched through that local wrapper. PGlite, the wrapper and environment setup are outside the proposed diff. I have not run the full monorepo suite or native PostgreSQL/CI here.Bounded retry policy
This is a temporary chain/address cooldown, not a guarantee that a later attempt cannot succeed. A new verified candidate, a changed deployment or a different creation-transaction hint can become useful during the interval; callers must wait for expiry, and operators can shorten or disable the interval. Eligibility follows the existing persisted error code; worker error classification is not changed here. There is no forced-retry bypass or permanent failure cache.
The new lookup adds one indexed history query to enabled similarity attempts. Production query plans and latency have not been benchmarked. Concurrent admission races before any completed failure exists remain outside this change.