Skip to content

perf: resolve member names with one getUsersByIds call - #97

Merged
amix merged 3 commits into
mainfrom
amix/batch-user-lookups
Nov 2, 2026
Merged

amix merged 3 commits into
mainfrom
amix/batch-user-lookups

Conversation

@amix

@amix amix commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Context

What was changed

  • The three commands resolve names with one getUsersByIds call. Unresolvable members, or a failed lookup, still fall back to user:<id>.
  • Trade-off: a failed lookup now drops every name, where it used to drop only that member's. Above 100 members, a failure in a later chunk also discards the chunks that succeeded.
  • workspaceUsers.getUsersByIds is allowed in read-only mode and has a spinner label.
  • Tests were updated to mock the batch call. groups view and channel members each cover both an unresolved member and a rejected batch.
  • @doist/comms-sdk 3.9.1 → 3.11.0. The lockfile changes only the SDK and its own pinned dependencies.

Out of scope

  • Single-user lookups (msg view, comment view, conversation with).

🤖 Generated with Claude Code

groups view, channel members, and conversation view fired one
getUserById per member in parallel. Resolve them with a single batched
getUsersByIds call instead; unresolvable members still fall back to
user:<id>. Allow the new read method in read-only mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amix amix added the 👀 Show PR requires passing checks before merge and independent human review before or after merge. label Nov 1, 2026
@amix
amix requested a review from scottlovegrove November 1, 2026 18:44
@amix
amix marked this pull request as ready for review November 1, 2026 18:44

@doistbot doistbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This PR replaces N parallel getUserById calls with a single batched getUsersByIds lookup in groups view, channel members, and conversation view, preserving the user:<id> fallback for unresolvable members and adding the new method to the read-only allowlist and spinner map.

Few things worth tightening:

  • SDK bump is required before merging: package.json and the lockfile still pin @doist/comms-sdk to 3.9.1, so clean installs fail type-check/build, and the missing method would throw at runtime before the .catch() fallback can kick in. Update both to the release containing getUsersByIds.
  • Duplicated fallback logic: the tolerant getUsersByIds(...).catch(() => ({})) + null-filtering pattern now appears three times (groups view, channel membership helpers, conversation view). Consider extracting a shared helper in src/lib/api.ts (e.g. next to buildUserNameMap) so the fallback and unresolved-member behavior live in one place.
  • Minor: conversation view no longer dedupes user IDs before the batch call, so repeated participant IDs get sent in the same request.

I also included a few optional follow-up notes in the details below.

Optional follow-up notes (3)
  • P3 src/commands/conversation/view.ts:18: The previous implementation deduped with new Set before looking users up, but this now passes [...userIds] as-is. For conversation view, userIds is built from conversation.userIds plus every message creator, so participants who authored messages appear many times and are sent repeatedly in the batch. Keep the dedupe: userIds: [...new Set(userIds)].
  • P3 src/commands/groups/groups.test.ts:255: This test no longer exercises the batch-rejection fallback. The previous mock made the lookup throw, which covered viewGroup's .catch(() => ({})) path; the new mixed response only covers a null entry for one member. If getUsersByIds rejects, every member should still fall back to user:<id> (JSON: name: null), but no groups view test would catch a regression there. Add a rejection case asserting the fallback for all members.
  • P3 src/commands/channel/members.test.ts:60: The default mock changed from throwing for unknown ids to returning { id: null }, so the existing falls back to user:<id> for unknown members test now exercises the null-entry branch instead of fetchUsersByIds's .catch(() => ({})) branch. A rejected getUsersByIds call is a distinct fallback path and is now untested in this suite. Add one rejection case asserting all members fall back.

Share Feedback • Review Logs

Comment thread src/commands/groups/view.ts Resolved
Comment thread src/commands/conversation/view.ts Resolved
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amix

amix commented Nov 1, 2026

Copy link
Copy Markdown
Member Author

Posted by Claudex on behalf of Amir:

Doistbot's other notes:

  • SDK bump (P1): the plan. It lands once feat: add getUsersByIds for batched workspace user lookups comms-sdk-typescript#125 is released; that thread stays open until then.
  • Rejected-batch fallback untested in groups view and channel members: fixed in 7b9a567. Each suite now has a rejection case asserting every member falls back to user:<id>, and both tests fail if the .catch is removed. conversation view already had one.
  • conversation view no longer dedupes: left as is. getUsersByIds dedupes before sending, so duplicate ids never reach the wire.
  • The wider failure scope of one batch (a failure now drops every name) is now called out in the PR description.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amix
amix merged commit ee7c93e into main Nov 2, 2026
7 checks passed
@amix
amix deleted the amix/batch-user-lookups branch November 2, 2026 05:30
doist-release-bot Bot added a commit that referenced this pull request Nov 2, 2026
## [3.8.2](v3.8.1...v3.8.2) (2026-11-02)

### Performance Improvements

* resolve member names with one getUsersByIds call ([#97](#97)) ([ee7c93e](ee7c93e))
@doist-release-bot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.8.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released 👀 Show PR requires passing checks before merge and independent human review before or after merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants