From 5c06a6804fd1dfdbf268b9877be2667d8c7c976c Mon Sep 17 00:00:00 2001 From: ivanauth Date: Wed, 14 Jan 2026 15:11:15 -0500 Subject: [PATCH 1/7] feat: enable expiration support by default in MCP server Signed-off-by: ivanauth --- internal/mcp/mcp.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/mcp/mcp.go b/internal/mcp/mcp.go index aef310ab..d169e51e 100644 --- a/internal/mcp/mcp.go +++ b/internal/mcp/mcp.go @@ -1129,6 +1129,8 @@ func newSpiceDBServer(ctx context.Context) (server.RunnableServer, error) { server.WithNamespaceCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), server.WithClusterDispatchCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), server.WithDatastore(ds), + // enable expiration support for relationships + server.WithEnableRelationshipExpiration(true), } return server.NewConfigWithOptionsAndDefaults(configOpts...).Complete(ctx) From b74cfad071658e4889c2a51b4c8e9cafc746bc6e Mon Sep 17 00:00:00 2001 From: ivanauth Date: Wed, 14 Jan 2026 16:32:45 -0500 Subject: [PATCH 2/7] ci: retry failed WASM tests Signed-off-by: ivanauth From 501cffdd55201afcd0e4c62d9f05a03e02e8a6de Mon Sep 17 00:00:00 2001 From: ivanauth Date: Wed, 21 Jan 2026 10:35:50 -0500 Subject: [PATCH 3/7] ci: re-run tests From fe3c821e192658949e8a600defdecb1adde8c995 Mon Sep 17 00:00:00 2001 From: ivanauth Date: Wed, 21 Jan 2026 10:54:55 -0500 Subject: [PATCH 4/7] ci: re-run flaky WASM test From c9647f31ce8dc15a00c91e59c450d55ae8610e15 Mon Sep 17 00:00:00 2001 From: ivanauth Date: Wed, 21 Jan 2026 10:59:22 -0500 Subject: [PATCH 5/7] ci: retry flaky WASM From 85c09168ae8aa1dfd40b3ef3ff154943443c33ed Mon Sep 17 00:00:00 2001 From: ivanauth Date: Wed, 21 Jan 2026 13:06:02 -0500 Subject: [PATCH 6/7] ci: add retry for flaky WASM tests --- .github/workflows/build-test.yaml | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index f51a711f..c3a7fb18 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -74,16 +74,21 @@ jobs: - name: "Run WASM Tests" # There's a whole bunch of vars in the environment that aren't needed for running this test, so we clear them out. # NOTE: if you need to do this in the future, I recommend bashing into the container and running `env | sort | less` - run: |- - GOOS=js \ - GOARCH=wasm \ - cleanenv \ - -remove-prefix GITHUB_ \ - -remove-prefix ANDROID_ \ - -remove-prefix JAVA_ \ - -remove-prefix DOTNET_ \ - -remove-prefix RUNNER_ \ - -remove-prefix HOMEBREW_ \ - -remove-prefix runner_ \ - -- \ - go test ./pkg/wasm/... -exec $(go env GOPATH)/bin/wasmbrowsertest + # NOTE: wasmbrowsertest can have flaky websocket timeouts, so we retry up to 3 times + uses: "nick-fields/retry@v3" + with: + max_attempts: 3 + timeout_minutes: 5 + command: |- + GOOS=js \ + GOARCH=wasm \ + cleanenv \ + -remove-prefix GITHUB_ \ + -remove-prefix ANDROID_ \ + -remove-prefix JAVA_ \ + -remove-prefix DOTNET_ \ + -remove-prefix RUNNER_ \ + -remove-prefix HOMEBREW_ \ + -remove-prefix runner_ \ + -- \ + go test ./pkg/wasm/... -exec $(go env GOPATH)/bin/wasmbrowsertest From 14cb05f28604ea45a6003bd56f4f4792bd8e3523 Mon Sep 17 00:00:00 2001 From: ivanauth Date: Fri, 23 Jan 2026 10:16:08 -0500 Subject: [PATCH 7/7] fix: prevent race in ConcurrentBatch when a batch fails with workers=1 The test TestConcurrentBatchWhenOneBatchFailsAndWorkersIsOne was flaky because there was a race between the semaphore release and errgroup's context cancellation. When a batch failed, it would release the semaphore (via defer) before errgroup cancelled the context, allowing the next iteration's sem.Acquire to succeed and execute an additional batch. Fix this by using an atomic.Bool flag that is set immediately when a batch returns an error. The main loop checks this flag after acquiring the semaphore, ensuring no new batches are launched after a failure. --- internal/grpcutil/batch.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/internal/grpcutil/batch.go b/internal/grpcutil/batch.go index 95c0395c..dfcbc324 100644 --- a/internal/grpcutil/batch.go +++ b/internal/grpcutil/batch.go @@ -4,6 +4,7 @@ import ( "context" "errors" "runtime" + "sync/atomic" "golang.org/x/sync/errgroup" "golang.org/x/sync/semaphore" @@ -47,6 +48,7 @@ func ConcurrentBatch(ctx context.Context, n int, batchSize int, maxWorkers int, maxWorkers = runtime.GOMAXPROCS(0) } + var failed atomic.Bool sem := semaphore.NewWeighted(int64(maxWorkers)) g, ctx := errgroup.WithContext(ctx) numBatches := (n + batchSize - 1) / batchSize @@ -55,12 +57,24 @@ func ConcurrentBatch(ctx context.Context, n int, batchSize int, maxWorkers int, break } + // After acquiring the semaphore, check whether a previous batch + // has already failed. This handles the race where a failing batch + // releases the semaphore before the errgroup cancels the context. + if failed.Load() { + sem.Release(1) + break + } + batchNum := i g.Go(func() error { defer sem.Release(1) start := batchNum * batchSize end := minimum(start+batchSize, n) - return each(ctx, batchNum, start, end) + err := each(ctx, batchNum, start, end) + if err != nil { + failed.Store(true) + } + return err }) } return g.Wait()