Skip to content

Instantly share code, notes, and snippets.

@K-Mistele
Created August 11, 2026 19:02
Show Gist options
  • Select an option

  • Save K-Mistele/a23fbbff713a82799c517abbc78408ca to your computer and use it in GitHub Desktop.

Select an option

Save K-Mistele/a23fbbff713a82799c517abbc78408ca to your computer and use it in GitHub Desktop.
Reproduce Rivet actor destroy retaining branch-backed SQLite data
#!/usr/bin/env bash
set -euo pipefail
dir="$(mktemp -d)"
project="rivet-sqlite-destroy-repro"
trap 'docker compose -p "$project" -f "$dir/compose.yml" down -v --remove-orphans >/dev/null 2>&1 || true; rm -rf "$dir"' EXIT
cat >"$dir/package.json" <<'EOF'
{"private":true,"type":"module","dependencies":{"rivetkit":"2.3.10"}}
EOF
cat >"$dir/server.ts" <<'EOF'
import { actor, setup } from "rivetkit"
const probe = actor({
state: { marker: "" },
actions: {
seed: (c, marker: string) => {
c.state.marker = `${marker}:${"x".repeat(262_144)}`
},
},
})
setup({ use: { probe }, sqlite: "remote", noWelcome: true }).start()
EOF
cat >"$dir/create.ts" <<'EOF'
import { createClient } from "rivetkit/client"
const client = createClient("http://default@engine:6420")
const handle = client.probe.getOrCreate(["destroy-repro"])
await handle.seed("survives-destroy")
await Bun.write("/shared/actor-id", await handle.resolve())
EOF
cat >"$dir/Dockerfile" <<'EOF'
FROM oven/bun:1.3.14-alpine
WORKDIR /app
COPY package.json ./
RUN bun install --production
COPY server.ts create.ts ./
CMD ["bun", "server.ts"]
EOF
cat >"$dir/compose.yml" <<'EOF'
services:
postgres:
image: postgres:17-alpine
environment:
POSTGRES_DB: rivet
POSTGRES_USER: rivet
POSTGRES_PASSWORD: rivet
healthcheck:
test: ["CMD-SHELL", "pg_isready -U rivet -d rivet"]
interval: 2s
timeout: 5s
retries: 30
engine:
image: rivetdev/engine:latest
command: ["start"]
environment:
RIVET__POSTGRES__URL: postgresql://rivet:rivet@postgres:5432/rivet
ports:
- "16420:6420"
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:6421/health"]
start_period: 30s
interval: 2s
timeout: 5s
retries: 30
configure:
image: curlimages/curl:8.12.1
command:
- -f
- -X
- PUT
- http://engine:6420/runner-configs/default?namespace=default
- -H
- "Content-Type: application/json"
- -d
- '{"datacenters":{"default":{"normal":{}}}}'
depends_on:
engine:
condition: service_healthy
app:
build: .
environment:
RIVET_ENDPOINT: http://default@engine:6420
volumes:
- .:/shared
depends_on:
configure:
condition: service_completed_successfully
EOF
dc=(docker compose -p "$project" -f "$dir/compose.yml")
"${dc[@]}" up -d --build
"${dc[@]}" exec -T postgres psql -U rivet -d rivet -v ON_ERROR_STOP=1 <<'SQL' >/dev/null
CREATE TABLE branches_before AS
SELECT DISTINCT substring(key FROM 4 FOR 16) AS branch_id
FROM kv
WHERE substring(key FROM 1 FOR 3) = decode('02302f', 'hex');
SQL
"${dc[@]}" exec -T app bun create.ts
actor_id="$(<"$dir/actor-id")"
branch_hex="$("${dc[@]}" exec -T postgres psql -U rivet -d rivet -Atc "
SELECT encode(branch_id, 'hex')
FROM (
SELECT DISTINCT substring(key FROM 4 FOR 16) AS branch_id
FROM kv
WHERE substring(key FROM 1 FOR 3) = decode('02302f', 'hex')
EXCEPT SELECT branch_id FROM branches_before
) branches;
")"
if [[ ! "$branch_hex" =~ ^[0-9a-f]{32}$ ]]; then
printf 'Expected exactly one new SQLite branch, got: %s\n' "$branch_hex" >&2
exit 1
fi
measure() {
"${dc[@]}" exec -T postgres psql -U rivet -d rivet -Atc "
SELECT 'branch_rows=' || count(*)
FROM kv
WHERE substring(key FROM 1 FOR 19) = decode('02302f${branch_hex}', 'hex');
SELECT 'refcount=' || (
get_byte(value, 0)::bigint
+ (get_byte(value, 1)::bigint << 8)
+ (get_byte(value, 2)::bigint << 16)
+ (get_byte(value, 3)::bigint << 24)
+ (get_byte(value, 4)::bigint << 32)
+ (get_byte(value, 5)::bigint << 40)
+ (get_byte(value, 6)::bigint << 48)
+ (get_byte(value, 7)::bigint << 56)
)
FROM kv
WHERE key = decode('02202f6c6973742f${branch_hex}', 'hex') || convert_to('/refcount', 'UTF8');
"
}
printf '\nBefore destroy:\n'
measure
curl -fsS -X DELETE "http://127.0.0.1:16420/actors/${actor_id}?namespace=default" >/dev/null
printf '\nAfter destroy:\n'
measure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment