← Back to PRs

#12954: feat(slack): Add channel name resolution with TTL cache

by trevorgordon981 open 2026-02-10 00:02 View on GitHub →
channel: slack stale
# PR: feat(slack): Add channel name resolution with TTL cache ## Summary Adds `SlackChannelCache` module for efficient Slack channel lookups with automatic caching. ## What New `src/slack/channel-cache.ts` module providing: - **In-memory cache** with 1-hour TTL for channel listings per workspace - **Name → ID resolution** with case-insensitive matching - **Multiple input format support:** - Channel names: `#general`, `general`, `GENERAL` - Slack mentions: `<#C123456|channel-name>` - Prefixed IDs: `slack:C123456`, `channel:C123456` - Raw IDs: `C123456`, `G789012` - **Pagination support** for workspaces with 1000+ channels - **Preference for non-archived** channels when duplicates exist - **Cache statistics** for monitoring (`getStats()`) ## Why Currently, resolving a channel name to ID requires API calls on every request. This adds: 1. **Latency** - each message send needs to resolve the target 2. **API rate limit pressure** - unnecessary `conversations.list` calls 3. **Complexity** - each caller reimplements resolution logic With this cache: - First call per workspace fetches and caches all channels - Subsequent calls use cached data (1-hour TTL) - Natural channel name usage in message tool (`target: "#general"`) - Handles all Slack channel reference formats uniformly ## Usage Example ```typescript import { slackChannelCache } from "./channel-cache.js"; // Resolve channel by name (case-insensitive) const channel = await slackChannelCache.resolveChannel(token, "#general"); // { id: "C03M3H7K4R7", name: "general", archived: false, isPrivate: false } // Or by Slack mention format const channel2 = await slackChannelCache.resolveChannel(token, "<#C03M3H7K4R7|general>"); // Get all channels as name→info map const channelMap = await slackChannelCache.getChannelsByName(token); // Map { "general" => {...}, "random" => {...}, ... } // Clear cache (e.g., after channel created/renamed) slackChannelCache.clearCache(token); // Monitor cache health const stats = slackChannelCache.getStats(); // { size: 1, tokens: 1, oldestEntryAge: 300000 } ``` ## Test Coverage - **14 tests**, all passing - Tests cover: - Basic channel fetching - Cache TTL behavior (no refetch within TTL) - Pagination handling - All input format variations - Case-insensitive matching - Archived channel handling - Cache clear operations - Statistics reporting ``` ✓ src/slack/channel-cache.test.ts (14 tests) 4ms ``` ## Breaking Changes None. This is a new additive module with no changes to existing code. ## Dependencies - Only depends on `@slack/web-api` (already a project dependency) - Uses existing `createSlackWebClient()` from `./client.js` ## Files Changed - `src/slack/channel-cache.ts` (new - 195 lines) - `src/slack/channel-cache.test.ts` (new - 195 lines) ## PR Metadata - **Title:** `feat(slack): Add channel name resolution with TTL cache` - **Branch:** `feature/slack-channel-name-resolution` - **Base:** `main` - **Labels:** `enhancement`, `slack` ## Checklist - [x] Code follows project style guidelines - [x] Tests pass (`npm test -- channel-cache`) - [x] All 145 Slack tests pass (`npm test -- src/slack/`) - [x] No breaking changes - [x] Self-contained (no fork-specific dependencies) - [x] Documentation included in this PR description <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR introduces a new `src/slack/channel-cache.ts` singleton (`slackChannelCache`) that fetches Slack channel listings via `conversations.list`, caches them in-memory with a 1-hour TTL per account, and provides helpers to resolve a variety of channel reference formats (IDs, `#name`, `<#id|name>`, etc.). It also adds a Vitest suite covering fetching, caching, pagination, resolution, cache clearing, and stats. The module fits alongside existing Slack helpers (e.g., `src/slack/resolve-channels.ts`) by centralizing channel listing/resolution logic and reducing repeated API calls for name→ID lookups. <h3>Confidence Score: 3/5</h3> - This PR is mergeable after fixing the cache keying and duplicate-name map behavior to avoid incorrect cross-token/channel resolutions. - Core logic is straightforward and tests cover basic behaviors, but the current cache key derivation can collide across tokens and `getChannelsByName` can return the wrong channel when duplicate names exist, which would cause incorrect routing in real use. - src/slack/channel-cache.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs