fix(seller): retry x402 middleware setup instead of caching a failed or empty build - #44
Open
chopmob-cloud wants to merge 1 commit into
Open
Conversation
…or empty build getPaymentMiddleware memoized the build promise unconditionally, so a null result (seller wallet not provisioned yet) or a rejection (e.g. a transient x402 facilitator outage during httpServer.initialize()) was cached for the life of the warm Lambda container. Every later request then replayed that first outcome, returning 503 or 500 until an unrelated cold start, even after Seller Setup ran or the facilitator recovered. Cache only a successfully built middleware: share the in-flight promise so concurrent first requests do not each rebuild, but clear the slot on a null or rejected result so the next request retries.
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
In
backend/lambdas/sellers/image-gen/index.js,getPaymentMiddleware()memoizes the middleware build promise unconditionally:Two of the promise's outcomes are not safe to cache for the life of a warm Lambda container:
httpServer.initialize()fetches/supportedfrom the x402 facilitator. If that call fails (a transient facilitator outage, a cold-start network blip), the promise rejects and the rejected promise is cached. Every later request in that container then awaits the same rejected promise and returns 500, until an unrelated cold start, even after the facilitator recovers.null(no wallet yet). If the first request arrives before Seller Setup provisions the payout wallet,buildAcceptsreturns[], the build resolves tonull, and that null is cached. The route keeps returning the 503 "Seller not configured" response for the life of the container even after Setup runs.Both are self-inflicted stranding: the container gets stuck on the first outcome it happened to see.
Fix
Cache only a successfully built middleware. Keep sharing the in-flight promise so concurrent first requests do not each rebuild, but clear the slot when the build resolves to
nullor rejects, so the next request retries.A successfully built middleware is still cached for the life of the container, so the steady-state behavior is unchanged.
Validation
Standalone reproduction of the caching wrappers (old vs new) against a build stub that fails once (facilitator down), then returns
null(no wallet), then succeeds:OLDstrands on its first outcome forever (one build, never retries).NEWretries after the transient failure and after Setup, then caches the successful middleware (build count stops at 3, so a successful build is still memoized and not rebuilt on later requests).node --checkpasses on the changed file.Happy to add a unit test for
getPaymentMiddlewareif you would like one in the suite.