Skip to content

fix(rivetkit): cache actor queries & automatic cache invalidation#4501

Merged
NathanFlurry merged 1 commit intomainfrom
03-24-fix_rivetkit_invalidate_cached_actor_ids_on_not_found_errors
Mar 25, 2026
Merged

fix(rivetkit): cache actor queries & automatic cache invalidation#4501
NathanFlurry merged 1 commit intomainfrom
03-24-fix_rivetkit_invalidate_cached_actor_ids_on_not_found_errors

Conversation

@NathanFlurry
Copy link
Copy Markdown
Member

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4501 March 24, 2026 22:45 Destroyed
@railway-app
Copy link
Copy Markdown

railway-app bot commented Mar 24, 2026

🚅 Deployed to the rivet-pr-4501 environment in rivet-frontend

Service Status Web Updated (UTC)
frontend-inspector 😴 Sleeping (View Logs) Web Mar 25, 2026 at 4:45 am
frontend-cloud 😴 Sleeping (View Logs) Web Mar 25, 2026 at 4:41 am
kitchen-sink ❌ Build Failed (View Logs) Web Mar 25, 2026 at 4:35 am
website 😴 Sleeping (View Logs) Web Mar 24, 2026 at 10:54 pm
mcp-hub ✅ Success (View Logs) Web Mar 24, 2026 at 10:45 pm
ladle ❌ Build Failed (View Logs) Web Mar 24, 2026 at 10:45 pm

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@NathanFlurry NathanFlurry changed the title fix(rivetkit): invalidate cached actor IDs on not_found errors fix(rivetkit): cache actor queries & automatic cache invalidation Mar 24, 2026
@claude
Copy link
Copy Markdown

claude bot commented Mar 24, 2026

---\n## PR Review: fix(rivetkit): cache actor queries and automatic cache invalidation\n\nThis PR introduces ActorResolutionState to cache actor ID resolution and add automatic retry-on-stale-cache behavior across all client operations (actions, queue sends, raw HTTP, raw WebSocket, and connection open). The approach is sound and well-tested.\n\n---\n\n### Whats good\n\n- Deduplication of concurrent resolve calls via pendingResolve is well-handled. Concurrent callers share the same in-flight queryActor promise, avoiding redundant round-trips.\n- Shared state between handle and connection: ActorHandleRaw.connect() passes its actorResolutionState directly to ActorConnRaw, so invalidation in one propagates to the other. This is the right design.\n- Single-retry semantics: retryOnInvalidResolvedActor uses a retried flag to guarantee at most one retry, preventing infinite loops even if the actor keeps getting destroyed.\n- Error filtering: shouldInvalidateResolvedActorId correctly limits invalidation to actor/not_found and actor/destroyed_* errors, so transient errors do not incorrectly bust the cache.\n- Test coverage: All four operation types (action, queue, HTTP fetch, raw WebSocket) plus connection open are covered with dedicated tests for both getOrCreate and get handles.\n\n---\n\n### Issues and observations\n\n1. Potential extra round-trip from actor/not_found on a never-created actor\n\nshouldInvalidateResolvedActorId treats any actor/not_found as a stale cache signal, including when the actor genuinely never existed. The behavior is safe (at most two requests), but it is worth a comment explaining callers should expect two requests when the actor does not exist.\n\n2. code.startsWith is a broad prefix match\n\nThis matches any future error code starting with destroyed_. A brief comment explaining why a prefix match is used instead of an exhaustive list would help future contributors understand the intent and avoid accidentally adding destroyed_-prefixed codes that should not trigger cache invalidation.\n\n3. shouldReconnectForStaleActor only fires during connection open, not mid-connection\n\nIf a connection is already established and the actor is then destroyed, the error is passed through to the application rather than triggering reconnect logic. This is intentional and reasonable, but a comment documenting that the retry guarantee applies only to the initial connection open would help callers understand the semantics.\n\n4. setResolvedActorId in connectWebSocket is redundant on the happy path\n\nAfter the WS init message, setResolvedActorId is called with the server-confirmed actor ID. But resolveActorId() was already called earlier in connectWebSocket, which already populated state.resolvedActorId. A comment clarifying whether this is intended as a server-confirmation safeguard would make the intent clearer.\n\n5. invalidateResolvedActorIdFromError is exported but only used internally\n\nThis function is only called by retryOnInvalidResolvedActor. Consider whether it should remain exported, or if keeping it unexported would reduce surface area and prevent misuse.\n\n6. resolveActorId silently falls through to uncached queryActor for create-type queries\n\nThis correctly skips caching for one-shot create queries, but every call to a create-backed handle re-queries. This matches pre-existing behavior and is correct. A brief comment would make the intentional bypass explicit.\n\n---\n\n### Minor nits\n\n- Formatting-only changes (whitespace, trailing newline, empty callback bodies) are fine.\n- Removed inline comments are consistent with the project guideline against documenting deltas.\n- The updated JSDoc on ActorAccessor interface methods is a nice addition.\n\n---\n\n### Summary\n\nThe core implementation is solid. The deduplication, retry semantics, and state-sharing design are all correct. The main actionable feedback:\n1. Document the two-request behavior for .get() on a non-existent actor.\n2. Add a comment on the startsWith prefix match rationale for destroyed errors.\n3. Add a comment on the mid-connection non-retry guarantee in shouldReconnectForStaleActor.\n\nNone of these are blockers.\n\nGenerated with Claude Code\n---

@NathanFlurry NathanFlurry force-pushed the 03-24-fix_rivetkit_invalidate_cached_actor_ids_on_not_found_errors branch from b86e608 to 3f97c6b Compare March 25, 2026 03:22
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4501 March 25, 2026 03:22 Destroyed
@NathanFlurry NathanFlurry force-pushed the 03-24-fix_rivetkit_invalidate_cached_actor_ids_on_not_found_errors branch from 3f97c6b to 031ab90 Compare March 25, 2026 04:11
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4501 March 25, 2026 04:11 Destroyed
@NathanFlurry NathanFlurry force-pushed the 03-24-fix_rivetkit_invalidate_cached_actor_ids_on_not_found_errors branch from 031ab90 to d85a1fe Compare March 25, 2026 04:32
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4501 March 25, 2026 04:32 Destroyed
@NathanFlurry NathanFlurry marked this pull request as ready for review March 25, 2026 04:32
Copy link
Copy Markdown
Member Author

NathanFlurry commented Mar 25, 2026

Merge activity

  • Mar 25, 4:56 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Mar 25, 4:56 AM UTC: @NathanFlurry merged this pull request with Graphite.

@NathanFlurry NathanFlurry merged commit 61fe9f6 into main Mar 25, 2026
14 of 20 checks passed
@NathanFlurry NathanFlurry deleted the 03-24-fix_rivetkit_invalidate_cached_actor_ids_on_not_found_errors branch March 25, 2026 04:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant