Fix stale PID race in ConsumerRegistry.unregister_name/1#3979
Fix stale PID race in ConsumerRegistry.unregister_name/1#3979alco wants to merge 8 commits intorefactor/static-logger-stringsfrom
Conversation
commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## refactor/static-logger-strings #3979 +/- ##
===============================================================
Coverage 88.74% 88.74%
===============================================================
Files 25 25
Lines 2425 2425
Branches 609 613 +4
===============================================================
Hits 2152 2152
Misses 271 271
Partials 2 2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
## Summary Add [TanStack Intent](https://github.com/TanStack/intent) skills to `@electric-sql/client` and `@electric-sql/y-electric` so AI coding agents can work with Electric correctly out of the box. Ships 9 skills covering the full developer journey from shape setup to production deployment. ## Approach Skills were generated using the `@tanstack/intent scaffold` workflow: 1. **Domain Discovery** — analyzed source code, docs, and maintainer interview to map 5 domains and 35 failure modes 2. **Tree Generator** — chose flat structure across 2 packages (8 skills in typescript-client, 1 in y-electric) 3. **Skill Generation** — wrote SKILL.md files with setup patterns, code examples verified against source, and wrong/correct mistake pairs Each skill targets a specific task (not a concept), with code examples validated against the current source at `v1.5.10`. ### Skills | Skill | Package | Type | Key coverage | |-------|---------|------|-------------| | `electric-shapes` | client | core | ShapeStream/Shape config, onError contract, WHERE clauses, type parsers | | `electric-proxy-auth` | client | core | Server proxy setup, ELECTRIC_PROTOCOL_QUERY_PARAMS, secret injection | | `electric-schema-shapes` | client | core | Schema + shape co-design, REPLICA IDENTITY FULL, replica modes | | `electric-debugging` | client | lifecycle | Error retry behavior, MissingHeadersError, fast-loop detection | | `electric-deployment` | client | lifecycle | Docker Compose, env vars, health checks, replication slot cleanup | | `electric-new-feature` | client | lifecycle | Full 5-step setup: schema → proxy → collection → queries → mutations | | `electric-orm` | client | composition | Drizzle/Prisma txid patterns, migration with REPLICA IDENTITY | | `electric-postgres-security` | client | security | Pre-deploy checklist: roles, grants, WAL, connection, publication | | `electric-yjs` | y-electric | composition | ElectricProvider, BYTEA parsing, resume state, awareness | ### Non-goals - No framework-specific skills (TanStack DB handles React/Vue/etc.) - No multi-shape-sync skill (experimental feature, may be removed) - No runtime code changes ### CI Workflows - `validate-skills.yml` — validates SKILL.md files on PRs touching `skills/` - `check-skills.yml` — checks for stale skills on release, opens review PR - `notify-intent.yml` — notifies TanStack/intent when source or docs change ## Verification ```bash cd packages/typescript-client && npx @tanstack/intent validate skills/ cd packages/y-electric && npx @tanstack/intent validate skills/ ``` Both pass with no errors or warnings. ## Files changed - `packages/typescript-client/skills/` — 8 SKILL.md files + 2 reference files (WHERE clause syntax, type parsers) - `packages/y-electric/skills/` — 1 SKILL.md file - `packages/*/package.json` — added `skills` + `bin` to `files`, `@tanstack/intent` devDependency, `bin` entry - `packages/*/bin/intent.mjs` — intent CLI shim - `.github/workflows/` — 3 new workflow files - `.gitignore` — added `_artifacts` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @electric-sql/experimental@6.0.12 ### Patch Changes - Updated dependencies [d1e08b8] - @electric-sql/client@1.5.12 ## @electric-sql/react@1.0.41 ### Patch Changes - Updated dependencies [d1e08b8] - @electric-sql/client@1.5.12 ## @electric-sql/client@1.5.12 ### Patch Changes - d1e08b8: Add TanStack Intent skills for AI agent guidance. Ships 9 skills covering shapes, proxy auth, schema design, debugging, deployment, new feature setup, ORM integration, Postgres security, and Yjs collaboration. ## @electric-sql/y-electric@0.1.38 ### Patch Changes - d1e08b8: Add TanStack Intent skills for AI agent guidance. Ships 9 skills covering shapes, proxy auth, schema design, debugging, deployment, new feature setup, ORM integration, Postgres security, and Yjs collaboration. - Updated dependencies [d1e08b8] - @electric-sql/client@1.5.12 ## expo-db-electric-starter@1.0.13 ### Patch Changes - Updated dependencies [d1e08b8] - @electric-sql/client@1.5.12 ## @core/sync-service@1.4.13 ### Patch Changes - 8daa822: Index `= ANY(array_field)` and `IN (const_list)` WHERE clause expressions for O(1) shape filtering. ANY clauses reuse the InclusionIndex (via single-element array containment), and IN clauses reuse the EqualityIndex (registering each value separately). At 1000 concurrent shapes, fan-out latency improves by 6x (ANY) and 15x (IN) compared to the previous linear scan. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
https://deploy-preview-3973--electric-next.netlify.app/blog/2026/03/06/agent-skills-now-shipping ## Summary - Announces that Electric, TanStack DB, and Durable Streams npm packages now ship with agent skills - Covers why versioned skills matter (training data staleness, new libraries absent from models) - Points readers to the kpb repo to try it out and the feedback skill to report issues ## Test plan - [ ] Preview the blog post on the website - [ ] Verify hero image renders correctly - [ ] Check all links resolve 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary - Announces that Electric, TanStack DB, and Durable Streams npm packages now ship with agent skills via the TanStack Intent system - Covers why versioned skills matter (training data staleness, new libraries absent from models) - Points readers to the Playbook repo to try it out and the feedback skill to report issues ## Test plan - [ ] Preview the blog post on the website - [ ] Verify hero image renders correctly - [ ] Check all links resolve (no dead links) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary - Adds a `CLAUDE.md` symlink pointing to `AGENTS.md` in `packages/sync-service` so that Claude Code automatically loads the sync-service guidelines into context. ## Test plan - [x] Verify symlink resolves correctly: `readlink packages/sync-service/CLAUDE.md` → `AGENTS.md` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The previous no-op implementation left stale PIDs in the ETS table. A naive lookup-then-delete fix would still be racey because the entry could be overwritten between the lookup and delete. Using :ets.match_delete/2 atomically deletes the entry only if the pid matches the calling (dying) process. Closes #3864 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dbb2f9f to
44ce5d6
Compare
Claude Code ReviewSummaryThis PR fixes the long-standing race in What is Working Well
Issues FoundImportant (Should Fix)1. Error message regression in File: Issue: The old Impact: If a consumer races with shape deletion (shape removed between consumer spawn and Suggested fix: Explicitly handle the case ShapeCache.ShapeStatus.fetch_shape_by_handle(stack_id, shape_handle) do
{:ok, shape} ->
state = State.initialize_shape(state, shape, config)
# ... continue init ...
:error ->
Logger.warning("Shape handle not found during consumer init, stopping",
shape_handle: shape_handle)
{:stop, :normal, state}
endOr at minimum preserve a descriptive raise so the handle appears in crash logs. 2. Missing changeset entry for the ConsumerRegistry race fix Issue: The Suggested fix: Add a Suggestions (Nice to Have)3. Issue #3864 code path #3 not addressed The linked issue identified three affected code paths. This PR addresses paths #1 (stale PID blocking 4. Unrelated files inflate the diff The diff includes GitHub Actions workflows ( Issue ConformanceIssue #3864 is well-specified with root cause analysis, three affected code paths, and a proposed fix. This PR implements a strictly better version of the proposed fix (atomic Previous Review StatusNo previous review. Review iteration: 1 | 2026-03-09 |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
unregister_name/1with an atomic:ets.match_delete/2that removes the ETS entry only if the pid matches the calling (dying) processmatch_deleteis atomicCloses #3864
Test plan
mix test test/electric/shapes/consumer_registry_test.exs— 16 tests pass (3 new)🤖 Generated with Claude Code