Skip to content

Commit 3ffe26a

Browse files
committed
perf(search): fetch Lucid page regions concurrently on a live read
A Lucid read made about 11 MCP calls in sequence: metadata, a metadata-only manifest, one fetch per page region (up to 8), then metadata again. At 1-2 s per call that ran past the 15 s live read deadline. The first metadata and manifest now run together, and region fetches run four at a time. Their validation still walks them in page and region order, and the before/after change checks are unchanged.
1 parent 9d8e4d8 commit 3ffe26a

2 files changed

Lines changed: 107 additions & 16 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { readLucidMcp } from '@/lib/sim-search/live/lucid-mcp'
3+
import type { ManagedSearchMcpClient } from '@/lib/sim-search/live/managed-mcp'
4+
5+
const ID = '0b6a3f0e-5a52-4c55-9d8c-6d2f2a1b9c11'
6+
const COUNTS = [2, 1]
7+
const metadataRow = {
8+
documentId: ID,
9+
viewUrl: `https://lucid.app/lucidchart/${ID}/view`,
10+
product: 'lucidchart',
11+
title: 'Fixture diagram',
12+
version: 7,
13+
pageCount: COUNTS.length,
14+
lastModified: '2026-10-01T12:00:00Z',
15+
}
16+
17+
function manifest(extra: Record<string, unknown> = {}) {
18+
return {
19+
document_id: ID,
20+
edit_url: `https://lucid.app/lucidchart/${ID}/edit`,
21+
title: 'Fixture diagram',
22+
metadata: { page_count: COUNTS.length, page_region_counts: COUNTS, ...extra },
23+
}
24+
}
25+
26+
function regionResponse(pageIndex: number, region: number) {
27+
const pageId = `page-${pageIndex}`
28+
return {
29+
...manifest({ page_index: pageIndex + 1 }),
30+
page_index: pageIndex + 1,
31+
page_id: pageId,
32+
text: JSON.stringify({
33+
pages: [
34+
{
35+
pageIndex,
36+
pageId,
37+
pageTitle: `Page ${pageIndex + 1}`,
38+
totalChunks: COUNTS[pageIndex],
39+
requestedChunks: [{ chunkIndex: region, data: { label: `p${pageIndex}r${region}` } }],
40+
},
41+
],
42+
}),
43+
}
44+
}
45+
46+
/** Region fetches settle in reverse request order, after a number of ticks, to expose ordering. */
47+
function lucidClient() {
48+
let inFlight = 0
49+
let maxInFlight = 0
50+
let regionCalls = 0
51+
const client: ManagedSearchMcpClient = {
52+
async call(name, args) {
53+
if (name === 'lucid_get_document_metadata') return metadataRow
54+
if (args.metadata_only) return manifest()
55+
const pageIndex = Number(args.page_index) - 1
56+
const region = Array.isArray(args.region_index) ? Number(args.region_index[0]) - 1 : 0
57+
const delay = 10 - regionCalls++
58+
inFlight++
59+
maxInFlight = Math.max(maxInFlight, inFlight)
60+
for (let tick = 0; tick < delay; tick++) await Promise.resolve()
61+
inFlight--
62+
return regionResponse(pageIndex, region)
63+
},
64+
}
65+
return { client, maxInFlight: () => maxInFlight }
66+
}
67+
68+
describe('readLucidMcp', () => {
69+
it('fetches page regions concurrently and assembles them in page and region order', async () => {
70+
const { client, maxInFlight } = lucidClient()
71+
const document = await readLucidMcp(client, { id: ID, kind: 'lucidchart', revision: '7' })
72+
expect(maxInFlight()).toBeGreaterThan(1)
73+
const pages = JSON.parse(document.content ?? '').pages as {
74+
pageId: string
75+
requestedChunks: { data: { label: string } }[]
76+
}[]
77+
expect(pages.map((page) => page.pageId)).toEqual(['page-0', 'page-1'])
78+
expect(pages.map((page) => page.requestedChunks.map((chunk) => chunk.data.label))).toEqual([
79+
['p0r0', 'p0r1'],
80+
['p1r0'],
81+
])
82+
})
83+
})

‎apps/sim/lib/sim-search/live/lucid-mcp.ts‎

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -322,44 +322,52 @@ function manifest(value: unknown, id: string, kind: string | undefined) {
322322
return { row, counts: counts as number[] }
323323
}
324324

325+
/**
326+
* Region fetches are independent provider reads; running them together keeps a full read inside
327+
* the live read deadline. Validation still walks them in page and region order.
328+
*/
329+
const REGION_FETCH_CONCURRENCY = 4
330+
325331
/** Complete, bounded provider pages preserve graph data; no returned URL is fetched. */
326332
export async function readLucidMcp(
327333
client: ManagedSearchMcpClient,
328334
reference: Pick<NativeDocument, 'id' | 'kind' | 'revision'>
329335
): Promise<NativeDocument> {
330-
const before = await metadata(client, reference.id)
336+
const [before, initialRaw] = await Promise.all([
337+
metadata(client, reference.id),
338+
client.call('fetch', { id: reference.id, metadata_only: true }),
339+
])
331340
if (!before) invalid('Lucid document metadata is incomplete or no longer readable.')
332341
if (
333342
(reference.kind && reference.kind !== before.kind) ||
334343
(reference.revision && reference.revision !== before.revision)
335344
)
336345
invalid('Lucid document changed since this result was issued. Search again before reading.')
337-
const initial = manifest(
338-
await client.call('fetch', { id: before.id, metadata_only: true }),
339-
before.id,
340-
before.kind
341-
)
346+
const initial = manifest(initialRaw, before.id, before.kind)
342347
if (
343348
initial.counts.length !== before.accessMetadata?.pageCount ||
344349
initial.row.title !== before.title
345350
)
346351
invalid('Lucid document coverage changed before reading. Search again.')
347352
const pages: Record<string, unknown>[] = []
348353
const output = () => JSON.stringify({ document_id: before.id, title: before.title, pages })
354+
const requests = initial.counts.flatMap((count, pageIndex) =>
355+
Array.from({ length: Math.max(1, count) }, (_, region) => ({ pageIndex, region, count }))
356+
)
357+
const responses = await mapWithConcurrency(requests, REGION_FETCH_CONCURRENCY, (request) =>
358+
client.call('fetch', {
359+
id: before.id,
360+
page_index: request.pageIndex + 1,
361+
...(request.count ? { region_index: [request.region + 1] } : {}),
362+
})
363+
)
364+
let next = 0
349365
for (let pageIndex = 0; pageIndex < initial.counts.length; pageIndex++) {
350-
const count = initial.counts[pageIndex]!
366+
const count = initial.counts[pageIndex] ?? 0
351367
let assembled: Record<string, unknown> | undefined
352368
const chunks: Record<string, unknown>[] = []
353369
for (let region = 0; region < Math.max(1, count); region++) {
354-
const fetched = manifest(
355-
await client.call('fetch', {
356-
id: before.id,
357-
page_index: pageIndex + 1,
358-
...(count ? { region_index: [region + 1] } : {}),
359-
}),
360-
before.id,
361-
before.kind
362-
)
370+
const fetched = manifest(responses[next++], before.id, before.kind)
363371
if (
364372
fetched.counts.some((value, index) => value !== initial.counts[index]) ||
365373
fetched.counts.length !== initial.counts.length ||

0 commit comments

Comments
 (0)