fix: use cached user list in /check instead of per-member GetUserInfo calls#64
Merged
WZ merged 3 commits intocodex/fix-ticket-prefix-dedupefrom Feb 23, 2026
Merged
Conversation
…dleListMissing Co-authored-by: WZ <719869+WZ@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] WIP address feedback on improving /check and preserving report statuses
fix: use cached user list in /check instead of per-member GetUserInfo calls
Feb 21, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Optimizes the Slack /check (missing reports) command by avoiding per-member users.info calls and instead leveraging the existing cached Slack user list to reduce latency and rate-limit exposure.
Changes:
- Reworked
handleListMissingto fetch Slack users once viagetCachedUsers(api)and do O(1) ID→user lookups via a map. - Added logging for
getCachedUsersfailures and continued with a degraded display mode (raw Slack IDs).
Comments suppressed due to low confidence (3)
internal/integrations/slack/slack.go:890
- This change affects observable behavior (which Slack endpoints are called, and the fallback behavior when
users.listfails) but there’s no automated coverage for/check/handleListMissing. Since the repo already has functional Slack tests with mock HTTP endpoints, please add a test that asserts/checkrelies onusers.list(and does not issue per-memberusers.infocalls) to prevent regressions.
// Build an ID→User map from the cached users list to avoid N individual
// GetUserInfo calls (one per team member) inside the loop below.
cachedUsers, err := getCachedUsers(api)
if err != nil {
log.Printf("list-missing: getCachedUsers error: %v", err)
}
internal/integrations/slack/slack.go:922
getCachedUsersfailure currently falls through to an emptyuserByIDmap, which means all members will lose name enrichment for this/checkinvocation (single-point-of-failure). If preserving names is important, consider falling back toapi.GetUserInfo(uid)only for IDs not found inuserByID(or whengetCachedUserserrors) so a transientusers.listissue doesn’t degrade the entire output.
cachedUsers, err := getCachedUsers(api)
if err != nil {
log.Printf("list-missing: getCachedUsers error: %v", err)
}
userByID := make(map[string]slack.User, len(cachedUsers))
for _, u := range cachedUsers {
userByID[u.ID] = u
}
type missingMember struct {
display string
userID string
}
var missing []missingMember
var missingIDs []string
for _, uid := range memberIDs {
u, found := userByID[uid]
nameCandidates := []string{uid}
if found {
if u.Profile.DisplayName != "" {
nameCandidates = append(nameCandidates, u.Profile.DisplayName)
}
if u.RealName != "" {
nameCandidates = append(nameCandidates, u.RealName)
}
}
if memberReportedThisWeek(uid, nameCandidates, reportedAuthorIDs, reportedAuthors) {
continue
}
if !found {
missing = append(missing, missingMember{display: uid, userID: uid})
missingIDs = append(missingIDs, uid)
continue
}
display := u.Profile.DisplayName
internal/integrations/slack/slack.go:894
- Building
userByIDasmap[string]slack.Usercopies everyslack.Userfrom the cachedusers.listresponse into a second data structure. In larger workspaces this can significantly increase per-/checkallocations and memory footprint. Consider mapping IDs to indices (or to a small struct with just the needed name fields) to avoid copying the fullslack.Userobjects.
cachedUsers, err := getCachedUsers(api)
if err != nil {
log.Printf("list-missing: getCachedUsers error: %v", err)
}
userByID := make(map[string]slack.User, len(cachedUsers))
for _, u := range cachedUsers {
userByID[u.ID] = u
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
handleListMissingwas callingapi.GetUserInfo(uid)once per team member on every/checkinvocation — N serial Slack API calls adding latency and rate-limit exposure proportional to team size.Changes
handleListMissing: Replace the per-memberapi.GetUserInfoloop with a singlegetCachedUsers(api)call (5-minute TTL cache) before the loop, then build anid→slack.Usermap for O(1) lookups per member.getCachedUsersfailures rather than silently discarding the error; gracefully degrades by displaying raw Slack IDs when the cache call fails.🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.