Skip to content

fix(plugin): store channel self overrides in kv#2275

Open
riderx wants to merge 1 commit into
mainfrom
codex/channel-self-kv-store
Open

fix(plugin): store channel self overrides in kv#2275
riderx wants to merge 1 commit into
mainfrom
codex/channel-self-kv-store

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 16, 2026

Summary (AI generated)

  • Add a CHANNEL_SELF_STORE KV-backed channel self override store with local Cache API reads.
  • Route old-device /channel_self set/get/delete override state through KV when the binding is available.
  • Teach /updates to honor KV-backed channel self overrides by resolving the override channel from the read replica.
  • Keep the existing database fallback when CHANNEL_SELF_STORE is not bound.

Motivation (AI generated)

Old devices still need server-side channel self overrides, but the hot channel self path should not rely on the primary database. Moving override state to replicated key-value storage keeps old plugin behavior working while allowing the new system to avoid primary database reads and writes.

Business Impact (AI generated)

This reduces primary database pressure on hot plugin endpoints and improves reliability for old devices during the transition to the replicated system. It keeps backward compatibility for customers who have not upgraded plugins yet while lowering operational risk on high-traffic paths.

Test Plan (AI generated)

  • bunx vitest run tests/channel-self-pg-client.unit.test.ts tests/update-channel-self-store.unit.test.ts
  • bun lint:backend
  • bunx eslint tests/channel-self-pg-client.unit.test.ts tests/update-channel-self-store.unit.test.ts
  • bun typecheck
  • git diff --check

Generated with AI

Summary by CodeRabbit

  • New Features

    • Per-device channel overrides can be stored in a local KV-backed store, reducing primary DB usage and enabling device-specific channel settings.
    • Route logic now picks storage path (legacy DB vs local KV) based on environment and plugin version.
  • Bug Fixes

    • Cache delete added and cache resilience improved.
    • Reads/writes/deletes now route correctly and, for newer plugin versions (v7.34.0+), skip server-side cleanup of legacy entries.
  • Tests

    • Added and updated unit tests covering KV routing, legacy vs new behavior, and override operations.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e3a285a-79c0-4712-a637-3df88b6efe78

📥 Commits

Reviewing files that changed from the base of the PR and between ae6948a and 8c0789b.

📒 Files selected for processing (9)
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/cache.ts
  • supabase/functions/_backend/utils/channelSelfStore.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/update.ts
  • tests/channel-self-pg-client.unit.test.ts
  • tests/channel_self.test.ts
  • tests/update-channel-self-store.unit.test.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/channelSelfStore.ts
  • tests/update-channel-self-store.unit.test.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • tests/channel-self-pg-client.unit.test.ts

📝 Walkthrough

Walkthrough

Adds Cloudflare KV + cache-backed per-device channel self override helpers, plugs store-aware wrapper helpers into channel_self plugin routes, extends Postgres queries to accept an override channel id, integrates stored overrides into update flow gating by plugin version, and adds unit tests verifying KV vs Postgres routing.

Changes

KV-backed per-device channel self overrides

Layer / File(s) Summary
KV store and cache infrastructure
supabase/functions/_backend/utils/channelSelfStore.ts, supabase/functions/_backend/utils/cloudflare.ts, supabase/functions/_backend/utils/cache.ts
New ChannelSelfOverride interface and KV utilities (getChannelSelfOverride, setChannelSelfOverride, deleteChannelSelfOverride) with JSON payload mapping and cache-first reads. CHANNEL_SELF_STORE KV namespace binding added to Cloudflare Workers types. CacheHelper.delete() method added for cache invalidation.
Channel self plugin route refactoring
supabase/functions/_backend/plugins/channel_self.ts
Adds wrapper helpers (getChannelSelfOverrideForDevice, deleteChannelSelfOverrideForDevice, upsertChannelSelfOverrideForDevice) that route per-device override operations between KV and Postgres based on isChannelSelfStoreEnabled(c). Replaces direct channel_devices table ops with wrappers and conditionally selects PG client for POST/PUT/DELETE handlers to avoid primary DB usage when KV/local-storage modes apply. POST/DELETE skip server-side migration cleanup in new local-storage versions.
Database query support for override channels
supabase/functions/_backend/utils/pg.ts
Adds requestInfosChannelByIdPostgres to fetch a channel by numeric id via active version join. Updates requestInfosPostgres signature to accept optional channelSelfOverrideChannelId and to branch between id-based override lookup and device-based override lookup or skip when appropriate.
Update flow integration of stored overrides
supabase/functions/_backend/utils/update.ts
Detects CHANNEL_SELF_STORE binding and plugin-version gating constants; dynamically imports channelSelfStore to fetch stored overrides for legacy plugin versions, forces channelDeviceCount to 0 when binding present, sets bypassChannelOverrides based on stored override presence, and passes stored override channel id into requestInfosPostgres.
Test coverage for KV routing
tests/channel-self-pg-client.unit.test.ts, tests/update-channel-self-store.unit.test.ts, tests/channel_self.test.ts
Adds an in-memory KV mock (createKvStore), updates fetch helpers to accept env, exposes named pg mocks, and adds tests asserting KV get/put/delete usage and absence of Postgres override/upsert calls when CHANNEL_SELF_STORE is bound; updates migration tests to reflect unchanged server-side channel_devices for new local-storage plugin versions; adds update flow test verifying stored override id propagation to requestInfosPostgres.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Cap-go/capgo#2266: Both PRs modify the PUT handler in channel_self.ts to adjust replica-style PG client configuration and conditional logic for override reads.
  • Cap-go/capgo#2057: Overlaps on updateWithPG control flow changes; this PR adds CHANNEL_SELF_STORE override routing while that PR adds update-enumeration rate limiting.

"🐰 I hopped through KV and PG,
saved device overrides where they should be.
Cache warmed, queries tuned, tests in tow,
a tiny rabbit's patch — now off I go! 🥕"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: storing channel self overrides in KV instead of relying solely on the primary database.
Description check ✅ Passed The description includes a summary of changes, motivation, business impact, and a comprehensive test plan with specific commands executed. However, it lacks detailed implementation details and does not follow the repository's template structure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/channel-self-kv-store

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 16, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing codex/channel-self-kv-store (8c0789b) with main (92d0d5a)2

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (34f239c) during the generation of this report, so 92d0d5a was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@riderx riderx force-pushed the codex/channel-self-kv-store branch from 55c50be to b7a5a71 Compare May 16, 2026 16:23
@riderx riderx marked this pull request as ready for review May 16, 2026 16:31
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 16, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@riderx riderx force-pushed the codex/channel-self-kv-store branch from b7a5a71 to 04c1d86 Compare May 16, 2026 16:34
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/plugins/channel_self.ts`:
- Around line 156-166: deleteChannelSelfOverrideForDevice currently skips legacy
Postgres deletes when CHANNEL_SELF_STORE (KV) is enabled; update the function
signature to accept an options object (e.g., { cleanupLegacyPg = false }) and,
when KV is enabled but cleanupLegacyPg is true, call deleteChannelDevicePg(c,
appId, deviceId, drizzleClient) in addition to (or instead of)
deleteChannelSelfOverride so legacy channel_devices rows are removed; update all
migration-call sites (the vX.34.0+ migration branches referenced) to call
deleteChannelSelfOverrideForDevice(..., { cleanupLegacyPg: true }) so PG
overrides are cleaned up during migration.

In `@tests/channel-self-pg-client.unit.test.ts`:
- Around line 152-170: Change the two added tests to run concurrently: replace
the two it(...) calls named "uses replica and KV for old plugin reads when
channel self store is bound" and "uses replica and KV for old plugin writes when
channel self store is bound" with it.concurrent(...) so they execute in
parallel; keep the same test bodies (using createKvStore(), fetchPut(),
fetchPost(), and the same assertions against getPgClientMock,
getChannelDeviceOverridePgMock, upsertChannelDevicePgMock, and kv.get/kv.put)
but only change the test declaration to it.concurrent to follow repository
parallelization rules.

In `@tests/update-channel-self-store.unit.test.ts`:
- Around line 74-108: Change the new test case "passes KV-backed channel_self
override channel id into update lookup" from using it(...) to it.concurrent(...)
so it runs in parallel; locate the test in
tests/update-channel-self-store.unit.test.ts (the spec that imports updateWithPG
and asserts requestInfosPostgresMock was called) and replace the it(...)
invocation with it.concurrent(...), leaving the body, assertions, and references
to updateWithPG and requestInfosPostgresMock unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: da5c6d44-1d62-4bc9-832b-76eb65ec8ecf

📥 Commits

Reviewing files that changed from the base of the PR and between 7a7226e and 04c1d86.

📒 Files selected for processing (8)
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/cache.ts
  • supabase/functions/_backend/utils/channelSelfStore.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/update.ts
  • tests/channel-self-pg-client.unit.test.ts
  • tests/update-channel-self-store.unit.test.ts

Comment thread supabase/functions/_backend/plugins/channel_self.ts
Comment thread tests/channel-self-pg-client.unit.test.ts Outdated
Comment thread tests/update-channel-self-store.unit.test.ts Outdated
@riderx riderx force-pushed the codex/channel-self-kv-store branch 3 times, most recently from ca1f971 to ae6948a Compare May 17, 2026 08:37
@riderx riderx force-pushed the codex/channel-self-kv-store branch from ae6948a to 8c0789b Compare May 17, 2026 08:45
@sonarqubecloud
Copy link
Copy Markdown

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