Skip to content

chore: fix serverless in rivetkit-core#4719

Draft
NathanFlurry wants to merge 1 commit into04-23-chore_rivetkit_impl_follow_up_reviewfrom
04-23-chore_fix_serverless
Draft

chore: fix serverless in rivetkit-core#4719
NathanFlurry wants to merge 1 commit into04-23-chore_rivetkit_impl_follow_up_reviewfrom
04-23-chore_fix_serverless

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
Copy link
Copy Markdown

railway-app Bot commented Apr 24, 2026

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

Service Status Web Updated (UTC)
kitchen-sink ❌ Build Failed (View Logs) Web Apr 24, 2026 at 6:02 am
website 😴 Sleeping (View Logs) Web Apr 24, 2026 at 1:49 am
frontend-cloud ❌ Build Failed (View Logs) Web Apr 24, 2026 at 1:42 am
ladle ✅ Success (View Logs) Web Apr 24, 2026 at 1:42 am
frontend-inspector ❌ Build Failed (View Logs) Web Apr 24, 2026 at 1:42 am
mcp-hub ✅ Success (View Logs) Web Apr 24, 2026 at 1:41 am

Copy link
Copy Markdown
Member Author

NathanFlurry commented Apr 24, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

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

@claude
Copy link
Copy Markdown

claude Bot commented Apr 24, 2026

PR Review: chore: fix serverless in rivetkit-core

Overview

This PR extracts shared serverless metadata types into a new rivetkit-shared-types crate to eliminate duplication between rivetkit-core and engine/packages/pegboard. It also improves error handling in the metadata fetch path, simplifies the NAPI build script, and updates the kitchen-sink example to use a published @rivetkit/sql-loader package.


Issues

Silent serialization failure (serverless.rs)

let mut response = serde_json::to_value(payload).unwrap_or_else(|_| json!({}));

If serde_json::to_value fails, this returns an empty JSON object, silently discarding all actor names and metadata without any log or error. Since ServerlessMetadataPayload only contains serializable primitives and serde_json::Value, serialization should not realistically fail — but if it does, this will produce a subtly broken response rather than a visible error. Prefer expect() with a message or proper ? propagation.

Post-processing to inject kind and drop null runner (serverless.rs)

The kind: {"serverless": {}} field is injected into the serialized JSON after the fact because it is not part of ServerlessMetadataPayload:

if let Some(envoy) = object.get_mut("envoy").and_then(|v| v.as_object_mut()) {
    envoy.insert("kind".to_owned(), json!({ "serverless": {} }));
}

Similarly, the null runner field is manually stripped after serialization. Both are workarounds for struct design. Two cleaner options:

  • Add a kind field to ServerlessMetadataEnvoy using a typed enum.
  • Annotate the runner field with #[serde(skip_serializing_if = "Option::is_none")] so it never appears in serialized output. If deserialization symmetry is needed, this is still safe — a missing field deserializes to None when default is used.

This would eliminate the post-serialization mutation entirely.

NAPI build: pre-built artifact detection removed

The previous build script skipped the napi build if a pre-built .node file existed, allowing CI to skip a redundant native compile when cross-compiled artifacts were already downloaded. That logic is now gone. If CI no longer provides pre-built artifacts, the removal is fine — but the PR description does not explain why. Worth confirming this does not regress CI build times.

Turbo.json glob inputs may cause excessive cache misses

../../../Cargo.lock is now an input, meaning any dependency update in the workspace (even unrelated crates) invalidates the Turbo cache for rivetkit-napi. The **/ globs across all of rivetkit-rust/packages and engine/packages have the same effect. This is more correct than before (previously rivetkit-core changes would not trigger a rebuild) but may cause more frequent full rebuilds in CI.

@rivetkit/sql-loader resolves to npm, not the workspace

pnpm-lock.yaml pins @rivetkit/sql-loader to the published version 2.2.1. If rivetkit-typescript/packages/sql-loader exists in the monorepo, this should use workspace:* so the kitchen-sink example always tests the local version. If the package is intentionally external-only, that is fine but worth noting explicitly.


Positives

  • Good deduplication. Extracting ServerlessMetadataPayload and friends into rivetkit-shared-types is the right call. The previous state had two private copies of the same structs.
  • Better error hygiene. Adding parse_error: String to InvalidResponseJson and introducing the dedicated InvalidEnvoyProtocolVersion variant (previously misreported as InvalidResponseJson) are clear improvements for observability.
  • execFileSync over execSync. Using execFileSync avoids shell injection and is the correct API when arguments are known at call time.
  • Turbo inputs now includes scripts/build.mjs and build.rs. Previously missing; changes to the build script now correctly invalidate the Turbo cache.

Minor Notes

  • ServerlessMetadataRunner is defined in shared-types but runner: None is always set at the call site in serverless.rs. If runner support is not planned, consider whether the field is needed in the shared struct at all.
  • The new shared-types crate has no [lib] section in Cargo.toml, which defaults correctly to src/lib.rs — fine as-is.
  • If you keep the unwrap_or_else fallback, at minimum log the error before falling back to json!({}) so failures are not completely silent.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Preview packages published to npm

Install with:

npm install rivetkit@pr-4719

All packages published as 0.0.0-pr.4719.23ea795 with tag pr-4719.

Engine binary is shipped via @rivetkit/engine-cli on linux-x64-musl, linux-arm64-musl, darwin-x64, and darwin-arm64. Windows users should use the release installer or set RIVET_ENGINE_BINARY.

Docker images:

docker pull rivetdev/engine:slim-23ea795
docker pull rivetdev/engine:full-23ea795
Individual packages
npm install rivetkit@pr-4719
npm install @rivetkit/react@pr-4719
npm install @rivetkit/rivetkit-napi@pr-4719
npm install @rivetkit/workflow-engine@pr-4719

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