Skip to content

feat: add membership caching and rest independence#4

Merged
dromzeh merged 6 commits into
mainfrom
capy/cache-membership-status
May 22, 2026
Merged

feat: add membership caching and rest independence#4
dromzeh merged 6 commits into
mainfrom
capy/cache-membership-status

Conversation

@capy-ai
Copy link
Copy Markdown
Contributor

@capy-ai capy-ai Bot commented May 22, 2026

This PR adds membership caching to eliminate repeated Discord REST API calls (~400ms per request) and allows REST endpoints to function independently of active WebSocket connections.

src/redis.rs:

  • Add MembershipEntry struct with TTL tracking
  • Add get_membership() and set_membership() methods with Redis (6h/5m positive/negative TTL) and in-memory fallback

src/discord.rs:

  • Add guild_member_addition and guild_member_removal event handlers
  • Update presence_update to always cache (not just when watcher exists) and opportunistically refresh membership cache
  • Add GUILD_MEMBERS intent and plumb guild_id through Handler

src/main.rs:

  • Update user_in_server_handler to check membership cache first, then Discord API fallback with write-through
  • Remove memory_cache field from WatcherGuard; stop evicting presence on WS close

README.md:

  • Update endpoint docs to reflect caching behavior and remove "WS required" caveat

Open ORIGI-001 ORIGI-001

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@capy-ai capy-ai Bot added the capy Generated by capy.ai label May 22, 2026
The repo's rust-toolchain.toml pins channel 1.92.0 but doesn't declare
rustfmt or clippy components, so GitHub's actions/checkout image
doesn't end up with them and `cargo fmt`/`cargo clippy` fail with
"is not installed for the toolchain".

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

@capy-ai capy-ai Bot left a comment

Choose a reason for hiding this comment

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

Added 1 comment

Comment thread src/discord.rs
If the bot is ever in multiple guilds, presence_update would still
populate the presence and membership caches for foreign-guild users.
Guard with the same guild_id check used in guild_member_addition /
guild_member_removal before doing any cache work.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@wilnavs wilnavs requested a review from dromzeh May 22, 2026 17:56
Comment thread src/discord.rs
Per review feedback: the bot is only intended to operate in the
configured guild. If it ever gets invited elsewhere we'd be paying
compute and emitting/caching out-of-scope data. Implement guild_create
to immediately leave any non-configured guild, and add guild_delete
logging so we notice if the bot is removed from the real guild.

This is defense-in-depth on top of the existing guild_id filters in
presence_update / guild_member_addition / guild_member_removal.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Comment thread src/redis.rs Outdated
Comment thread src/redis.rs Outdated
Comment thread src/discord.rs
wilnavs and others added 2 commits May 22, 2026 18:07
Per review feedback (#4):

- Add src/consts.rs with all TTLs, HTTP/WS tunables, Redis bootstrap
  knobs and an optional DEFAULT_GUILD_ID compile-time fallback so the
  env var can be omitted in our canonical deployment.
- Rename src/redis.rs -> src/cache.rs. The old name shadowed the
  redis crate import and made the file feel like a Redis driver; it
  is really a two-tier cache. While there, factor the
  "try Redis, fall through to memory on Unavailable" pattern into
  redis_read returning RedisRead::{Hit, Miss, Unavailable} so
  get / get_membership stop duplicating the dance.
- Move membership TTL freshness check onto MembershipEntry.
- main.rs consumes all magic numbers from consts; resolve_guild_id
  encapsulates the GUILD_ID env / DEFAULT_GUILD_ID fallback.

No behavioural change beyond DEFAULT_GUILD_ID being a new optional
escape hatch (defaults to None == current behaviour).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Per follow-up review:
- Hardcode DEFAULT_GUILD_ID to 982385887000272956 (the Antifield guild)
  so the GUILD_ID env var becomes optional.
- Restructure src/consts.rs into nested modules grouped by subject
  (ttl, http, ws, redis_boot, discord) — call sites now read as
  ttl::PRESENCE_MS, http::LISTEN_PORT, ws::PING_INTERVAL, etc.
- Drop the redundant *_TTL_ suffix on the names since they live inside
  the `ttl` module.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Member

@dromzeh dromzeh left a comment

Choose a reason for hiding this comment

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

lgtm

@dromzeh dromzeh merged commit d1296ec into main May 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

capy Generated by capy.ai

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants