[PR #112] [MERGED] perf: batch tag resolution to reduce action→query round-trips #260

Closed
opened 2026-02-15 17:16:32 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/openclaw/clawhub/pull/112
Author: @mkrokosz
Created: 2/2/2026
Status: Merged
Merged: 2/14/2026
Merged by: @steipete

Base: mainHead: perf/batch-resolve-tags


📝 Commits (4)

  • 3f96bee perf: batch tag resolution to reduce action→query round-trips
  • 2be0a5e fix: add null guard and short-circuit for empty tags
  • 3c0a990 Merge remote-tracking branch 'origin/main' into temp/pr112-from-remote
  • 857ab8f refactor: batch resolve tags in v1 API (#112) (thanks @mkrokosz)

📊 Changes

5 files changed (+328 additions, -66 deletions)

View changed files

📝 CHANGELOG.md (+1 -0)
📝 convex/httpApiV1.handlers.test.ts (+212 -3)
📝 convex/httpApiV1.ts (+99 -63)
📝 convex/skills.ts (+8 -0)
📝 convex/souls.ts (+8 -0)

📄 Description

Summary

  • Batch version tag resolution in list endpoints to reduce N sequential ctx.runQuery() calls to 1
  • Applies to both skills and souls list/get endpoints

Problem

The resolveTags function was called per-item in list responses, with each call making sequential ctx.runQuery() calls for each tag. For a list of 20 skills with 5 tags each, this resulted in 100 separate action→query round-trips.

Solution

  • Add getVersionsByIds batch query to skills.ts and souls.ts
  • Replace per-item tag resolution with batch resolution that:
    1. Collects all version IDs from all items
    2. Fetches all versions in a single query
    3. Maps results back to each item

Performance Impact

Scenario Before After
List 20 skills, 5 tags each 100 action→query round-trips 1 round-trip
Single skill detail, 5 tags 5 round-trips 1 round-trip

Changes

  • convex/skills.ts: Add getVersionsByIds query
  • convex/souls.ts: Add getVersionsByIds query
  • convex/httpApiV1.ts: Replace resolveTags/resolveSoulTags with batch versions
  • convex/httpApiV1.handlers.test.ts: Update tests to verify batch behavior

API Impact

None - response format is unchanged.

🤖 Generated with Claude Code

Greptile Overview

Greptile Summary

This PR batches version-tag resolution for skills and souls in the v1 HTTP API handlers. Instead of resolving each tag via repeated ctx.runQuery() calls per item, handlers now collect all version IDs from the response, fetch the corresponding versions via a single getVersionsByIds query, and map the resolved version strings back onto each item.

The approach fits the existing Convex pattern of keeping list endpoints cacheable/efficient while doing additional enrichment in the HTTP layer.

One correctness issue to address: the new batch resolvers assume the batch query always returns an array, and can throw when there are no tags / the query returns null.

Confidence Score: 2/5

  • This PR is not safe to merge as-is due to a crash in the new batch tag resolution path when the batch query returns null/undefined.
  • Score is reduced because the new resolveTagsBatch/resolveSoulTagsBatch assume the batch query returns an iterable array and will throw if it returns null (observed in tests when listing skills with no tags / when runQuery mock returns null). The remaining changes are straightforward and localized, and the performance intent is sound.
  • convex/httpApiV1.ts (batch tag resolver helpers); also review the new batch queries in convex/skills.ts and convex/souls.ts for expected input sizes/limits.

(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!

Context used:

  • Context from dashboard - AGENTS.md (source)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/openclaw/clawhub/pull/112 **Author:** [@mkrokosz](https://github.com/mkrokosz) **Created:** 2/2/2026 **Status:** ✅ Merged **Merged:** 2/14/2026 **Merged by:** [@steipete](https://github.com/steipete) **Base:** `main` ← **Head:** `perf/batch-resolve-tags` --- ### 📝 Commits (4) - [`3f96bee`](https://github.com/openclaw/clawhub/commit/3f96beee02e438514709533812fea375a8da7e15) perf: batch tag resolution to reduce action→query round-trips - [`2be0a5e`](https://github.com/openclaw/clawhub/commit/2be0a5eb14c228d7fdf9796b329f8550ba146360) fix: add null guard and short-circuit for empty tags - [`3c0a990`](https://github.com/openclaw/clawhub/commit/3c0a990e915350dd312e07c759006da30d7440ef) Merge remote-tracking branch 'origin/main' into temp/pr112-from-remote - [`857ab8f`](https://github.com/openclaw/clawhub/commit/857ab8f118682b2f2dcb5c1e0e64dc798bb8da8d) refactor: batch resolve tags in v1 API (#112) (thanks @mkrokosz) ### 📊 Changes **5 files changed** (+328 additions, -66 deletions) <details> <summary>View changed files</summary> 📝 `CHANGELOG.md` (+1 -0) 📝 `convex/httpApiV1.handlers.test.ts` (+212 -3) 📝 `convex/httpApiV1.ts` (+99 -63) 📝 `convex/skills.ts` (+8 -0) 📝 `convex/souls.ts` (+8 -0) </details> ### 📄 Description ## Summary - Batch version tag resolution in list endpoints to reduce N sequential `ctx.runQuery()` calls to 1 - Applies to both skills and souls list/get endpoints ## Problem The `resolveTags` function was called per-item in list responses, with each call making sequential `ctx.runQuery()` calls for each tag. For a list of 20 skills with 5 tags each, this resulted in 100 separate action→query round-trips. ## Solution - Add `getVersionsByIds` batch query to `skills.ts` and `souls.ts` - Replace per-item tag resolution with batch resolution that: 1. Collects all version IDs from all items 2. Fetches all versions in a single query 3. Maps results back to each item ## Performance Impact | Scenario | Before | After | |----------|--------|-------| | List 20 skills, 5 tags each | 100 action→query round-trips | 1 round-trip | | Single skill detail, 5 tags | 5 round-trips | 1 round-trip | ## Changes - `convex/skills.ts`: Add `getVersionsByIds` query - `convex/souls.ts`: Add `getVersionsByIds` query - `convex/httpApiV1.ts`: Replace `resolveTags`/`resolveSoulTags` with batch versions - `convex/httpApiV1.handlers.test.ts`: Update tests to verify batch behavior ## API Impact None - response format is unchanged. 🤖 Generated with [Claude Code](https://claude.ai/code) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR batches version-tag resolution for skills and souls in the v1 HTTP API handlers. Instead of resolving each tag via repeated `ctx.runQuery()` calls per item, handlers now collect all version IDs from the response, fetch the corresponding versions via a single `getVersionsByIds` query, and map the resolved version strings back onto each item. The approach fits the existing Convex pattern of keeping list endpoints cacheable/efficient while doing additional enrichment in the HTTP layer. One correctness issue to address: the new batch resolvers assume the batch query always returns an array, and can throw when there are no tags / the query returns `null`. <h3>Confidence Score: 2/5</h3> - This PR is not safe to merge as-is due to a crash in the new batch tag resolution path when the batch query returns null/undefined. - Score is reduced because the new `resolveTagsBatch`/`resolveSoulTagsBatch` assume the batch query returns an iterable array and will throw if it returns `null` (observed in tests when listing skills with no tags / when `runQuery` mock returns null). The remaining changes are straightforward and localized, and the performance intent is sound. - convex/httpApiV1.ts (batch tag resolver helpers); also review the new batch queries in convex/skills.ts and convex/souls.ts for expected input sizes/limits. <!-- greptile_other_comments_section --> <sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub> **Context used:** - Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=a1d58d20-b4dd-4cbb-973a-9fd7824e1921)) <!-- /greptile_comment --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-15 17:16:32 -05:00
yindo closed this issue 2026-02-15 17:16:32 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: openclaw/clawhub#260