Skip to content

feat(rivetkit): add getParams for dynamic connection parameters#4473

Merged
NathanFlurry merged 3 commits intomainfrom
add-client-getparams
Mar 21, 2026
Merged

feat(rivetkit): add getParams for dynamic connection parameters#4473
NathanFlurry merged 3 commits intomainfrom
add-client-getparams

Conversation

@NathanFlurry
Copy link
Member

Description

Adds a getParams callback option to QueryOptions that is lazily evaluated each time a new connection is opened. This enables patterns like refreshing JWT tokens on every connection or reconnect.

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

Added two new integration tests in the driver test suite:

  1. Verifies getParams is called once per connection with fresh values
  2. Verifies that getParams errors are surfaced as ActorError with code get_params_failed and that the connection retries successfully

Implementation Details

  • getParams is called immediately before opening a WebSocket connection
  • Errors from getParams clear the message queue, reject pending promises, and dispatch an ActorError
  • Both params and getParams can be provided; getParams takes precedence for connection-based flows
  • Documentation updated across authentication, connections, and JavaScript client pages

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my feature works

Adds a getParams callback option to QueryOptions that is called each time a new connection is opened. This enables patterns like refreshing a JWT on every connection or reconnect. Errors from getParams are surfaced as ActorError with code 'get_params_failed' and allow the connection to retry.

Includes new driver tests to verify getParams is called per connection and that errors are properly surfaced and retried. Documentation updated across authentication, connections, and client JavaScript pages.
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4473 March 21, 2026 20:23 Destroyed
@railway-app
Copy link

railway-app bot commented Mar 21, 2026

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

Service Status Web Updated (UTC)
frontend-inspector 😴 Sleeping (View Logs) Web Mar 21, 2026 at 8:39 pm
frontend-cloud ✅ Success (View Logs) Web Mar 21, 2026 at 8:38 pm
website 😴 Sleeping (View Logs) Web Mar 21, 2026 at 8:33 pm
mcp-hub ✅ Success (View Logs) Web Mar 21, 2026 at 8:24 pm
ladle ❌ Build Failed (View Logs) Web Mar 21, 2026 at 8:24 pm

getParams was only wired into connect() and webSocket(). This meant
action(), send(), and fetch() would silently omit connection params
when only getParams was provided, breaking authentication for those
code paths.
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4473 March 21, 2026 20:25 Destroyed
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 21, 2026

More templates

@rivetkit/cloudflare-workers

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/cloudflare-workers@4473

@rivetkit/framework-base

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/framework-base@4473

@rivetkit/next-js

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/next-js@4473

@rivetkit/react

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/react@4473

rivetkit

pnpm add https://pkg.pr.new/rivet-dev/rivet/rivetkit@4473

@rivetkit/sql-loader

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/sql-loader@4473

@rivetkit/sqlite-vfs

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/sqlite-vfs@4473

@rivetkit/traces

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/traces@4473

@rivetkit/workflow-engine

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/workflow-engine@4473

@rivetkit/virtual-websocket

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/virtual-websocket@4473

@rivetkit/engine-runner

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner@4473

@rivetkit/engine-runner-protocol

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner-protocol@4473

commit: 291ef5b

@claude
Copy link

claude bot commented Mar 21, 2026

PR Review: feat(rivetkit): add getParams for dynamic connection parameters

Overall this is a well-structured feature with good test coverage. A few issues worth addressing.


Bug: Inconsistent error handling between ActorConnRaw and ActorHandleRaw

In actor-conn.ts, #resolveConnectionParams catches getParams errors, wraps them in ActorError with code get_params_failed, dispatches them, clears the message queue, and rejects pending promises before re-throwing.

In actor-handle.ts, #resolveConnectionParams has no such handling — raw errors propagate directly. This means action(), send(), fetch(), and queue sends will throw the original error from getParams rather than an ActorError with get_params_failed. Users catching errors by error.group === "client" && error.code === "get_params_failed" won't get consistent behavior across code paths. The same gap exists in queue.ts.


Docs: Examples replace params instead of augmenting

In authentication.mdx and connections.mdx, the existing params example is swapped out for a getParams example. Since params is still the right choice for static values (and is simpler), replacing rather than adding a comparison risks guiding users toward unnecessary async indirection. The javascript.mdx change correctly shows both as tabs — the other pages should match that approach.


Minor: getParams could accept synchronous callbacks

The type () => Promise<unknown> requires async callbacks. A union () => unknown | Promise<unknown> would be more ergonomic for users who want to return a computed static value without wrapping in async.


Test gap: getParams error not tested for action()/fetch() paths

The new tests cover the WebSocket connect() path. Given the inconsistency noted above, a test verifying error behavior when getParams throws during action() or fetch() would catch regressions.


Nit: Redundant await in ActorHandleRaw.#resolveConnectionParams

return await this.#getParams() inside an already-async function is equivalent to return this.#getParams(). Minor but worth keeping consistent.

@claude
Copy link

claude bot commented Mar 21, 2026

PR Review: feat(rivetkit): add getParams for dynamic connection parameters

The feature is well-motivated and the overall design is sound. A few issues worth addressing.

Bug: Asymmetric error handling in #resolveConnectionParams

The two implementations of #resolveConnectionParams behave very differently on error.

actor-conn.ts has full error handling: wraps the error as ActorError, clears queued messages, rejects pending promises, dispatches the error, then re-throws.

actor-handle.ts has no error handling at all — getParams errors propagate raw. When getParams throws during a webSocket() call, the caller gets a plain Error instead of an ActorError, bypassing all the cleanup logic.

Missing test coverage: getParams with webSocket()

Both the tests and the documentation focus on connect(). The webSocket() method was also updated to use getParams, but there are no tests for that path — including error handling.

getParams silently does not apply to HTTP actions and fetch()

actor-handle.ts has two call sites that still use this.#params directly: the HTTP action code around line 168 (HEADER_CONN_PARAMS) and fetch() at line 262. If a user provides only getParams without a static params, both paths silently send undefined. The PR description says this is intentional, but it is not documented in the JSDoc. A user who replaces params with getParams everywhere may be surprised that action calls stop receiving auth params.

createQueueSender initialized with stale this.#params

The queue sender is created at construction with params: this.#params. This is correct today since the queue sender is for HTTP-based sends (same scope as the action path). A brief comment explaining that this intentionally does not call #resolveConnectionParams() would help future readers.

Breaking change: webSocket() is now async

webSocket() was previously synchronous. Making it async is unavoidable but is a breaking change for any code that relied on the synchronous return value. This should be noted in the changelog or release notes.

Minor: JSDoc for getParams should document interaction with params

The current description only says it applies to .connect() and .webSocket(). It should also note that getParams takes precedence over params for WebSocket connections, and that params is still used for HTTP action calls and fetch().

Tests look good otherwise

The two new test cases cover the core scenarios well: fresh params per connection and error surfacing with retry recovery. The use of vi.waitFor for the retry test is appropriate given the async reconnect flow.

@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4473 March 21, 2026 20:33 Destroyed
@NathanFlurry NathanFlurry merged commit f65bf1c into main Mar 21, 2026
15 of 19 checks passed
@NathanFlurry NathanFlurry deleted the add-client-getparams branch March 21, 2026 20:45
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