Repository navigation
perf(relay): index default channels and read them from the replica at AUTH - #9222
Open
TheSentinel454 wants to merge 5 commits into
Open
TheSentinel454 wants to merge 5 commits into
TheSentinel454 wants to merge 5 commits into
Conversation
TheSentinel454
marked this pull request as ready for review
November 6, 2026 22:14
🔐 Codex Security Review
Review SummaryOverall Risk: NONE
FindingsNo concrete security, correctness, or reliability findings were identified. Notes
Generated by Codex Security Review | |
TheSentinel454
force-pushed
the
elrond/auto-join-auth-index
branch
from
November 6, 2026 22:19
a50be7a to
2cfb952
Compare
… AUTH On a community that does not require relay membership, every admitted human AUTH lists the default channels the person has never joined. That read walked every open channel in the community on the writer pool to find the few with auto_join set. - Migration 0085 adds a partial index on channels (community_id) holding only effective default channels (flagged, open, unarchived, not deleted stream channels), built inline under 1s lock / 5s statement budgets as 0049 does, with an exact-definition check so a prebuilt CONCURRENTLY index verifies. - Db::list_never_joined_auto_join_channels_routed reads the bounded replica, falling back to the writer as pending_default_channel_join_routed does. put_first_member decides again under the membership lock, so a stale answer can only skip a channel joined since or defer one flagged since. No behavior change. Signed-off-by: Luke Tornquist <tornquist@squareup.com> Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Luke Tornquist <tornquist@squareup.com>
Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Luke Tornquist <tornquist@squareup.com>
…build The 0083 prebuild test held a channels writer lock while running every migration, so 0087's inline index build hit its lock timeout. Run it only through 0083, and add the matching check that 0087 over a concurrent prebuild neither waits for writers nor replaces the index. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Luke Tornquist <tornquist@squareup.com>
TheSentinel454
force-pushed
the
elrond/auto-join-auth-index
branch
from
November 6, 2026 23:46
45d812c to
8b74366
Compare
The AUTH auto-join list can now come from the bounded replica, so a channel unflagged within the replica budget could still be listed. put_first_member already decides membership history under the channel lock; it now also skips a channel that is no longer auto_join, so a stale candidate writes nothing. Both callers are default-channel joins. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Luke Tornquist <tornquist@squareup.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
In roster-free communities, every AUTH runs
list_never_joined_auto_join_channelsto join the caller to the community's default (auto_join) channels. Two changes make that read cheap, plus one recheck that keeps a stale read from joining an unflagged channel.idx_channels_auto_joinonchannels (community_id) WHERE auto_join AND channel_type = 'stream' AND visibility = 'open' AND archived_at IS NULL AND deleted_at IS NULL. Without it, the query plans throughidx_channels_community_visibility, reads every open channel in the community, and filters nearly all of them away, because default channels are a handful out of thousands. With it, the planner probes only the flagged rows.Db::list_never_joined_auto_join_channels_routedroutes throughroute_read(.., RoutePredicate::Bounded, ReaderOperation::Authorization), the same aspending_default_channel_join_routed. A replica error falls back to the writer, and a cancelled statement propagates. The only production caller,join_never_joined_channelsinside_effects.rs, uses it. With no replica budget configured, it reads the writer as before.Why a stale read is safe
put_first_memberdecides on the writer, under the channel's membership lock, so a stale candidate list cannot cause a wrong join:put_first_membernow rechecksauto_joinunder the lock. Both of its callers are default-channel joins.put_memberand counted inbuzz_auto_join_failures_total, as today.Database review checklist (
docs/database.md)Phase: expand only. Nothing comes before it. Nothing needs to follow: the deployed relay's query uses the index as soon as it exists.
No trigger, function, procedure, rule, or foreign key is added.
No migration mutates existing rows, and there is no backfill.
Not a contract migration.
Rule 4 locations:
migrations/0087_channels_auto_join_index.sqlandschema/tables/public/channels.sql.admin_schema_parity_between_desired_state_and_migrationsnow comparesidx_channels_auto_joinalongsideidx_channels_listed_name, between the desired-state and migrated catalogs. No new files, soschema/schema.sqlis unchanged. A partial btree index needs noreconcile-schema-after-pgschema.sqlstep.Deployed relay: the index is additive and the SQL text is unchanged. The running relay ignores it or uses it. Its plan was checked with
EXPLAINon a migrated database (below).Locks and build:
SET LOCAL lock_timeout = '1s'andstatement_timeout = '5s'. The migration builds the index inline only whento_regclassfinds none, then verifiespg_get_indexdefandindisvalid/indisready/indislive, and stops if the definition differs. Prebuild for deployments that apply migrations out of band (in the migration header):Migration number
0087. Main is at0086. #9108 (#9108) also needs new numbers. Whichever PR merges second renumbers.Tests
never_joined_auto_join_channels_routed_reads_the_bounded_replica(buzz-db,postgres_tests) seeds a writer and a replica with different default channels. It asserts the writer's channel with no budget, the replica's with a 5 s budget, and the writer's again when the replica fence is stale. A mutant that always reads the writer fails it.embedded_migrator_contains_consolidated_initial_schemapins the migration count, the timeouts, and the absence ofCONCURRENTLY.first_member_put_joins_once_and_never_undoes_a_leavenow also asserts thatput_first_memberwrites nothing for a channel that is not, or is no longer,auto_join.auto_join_index_migration_accepts_a_prebuild_without_waiting_for_writersruns0087over a concurrent prebuild while a channel writer holds its lock: it neither waits nor replaces the index.migration_schema_listed_name_index_validates_a_prebuildnow stops at0083, since later migrations that build their own index inline need the lock it holds.0087against an existing index succeeds, and running it against a wrong-definition index stops.EXPLAINof the query, as both a custom and a generic (prepared) plan, usesidx_channels_auto_join.What got simpler
Nothing was removed, but the concept count stays flat. The routed method replaces the writer-only
Dbmethod instead of sitting beside it. Both arms share one connection-level helper, so the SQL lives in one place.🤖 Generated with Claude Code