Skip to content

Commit 166a6d1

Browse files
committed
fix(knowledge): remember a saturated reach only once its count succeeded, and read the Tin flag before the index
1 parent 91a04d4 commit 166a6d1

4 files changed

Lines changed: 38 additions & 12 deletions

File tree

‎apps/sim/lib/knowledge/search/queries.test.ts‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,38 @@ describe('permitted-document planner', () => {
19091909
expect(reachCounts()).toHaveLength(2)
19101910
})
19111911

1912+
it('does not remember a saturated reach whose count ran out of time', async () => {
1913+
dbChainMockFns.execute.mockImplementation(async (query) => {
1914+
const statement = render(query).sql
1915+
if (isProbeStatement(statement)) return [{ id: null, connectorId: null, saturated: true }]
1916+
if (statement.includes('EXPLAIN'))
1917+
return [{ 'QUERY PLAN': [{ Plan: { 'Plan Rows': 1_000_000 } }] }]
1918+
if (statement.includes(') reached'))
1919+
throw Object.assign(new Error('canceling statement due to statement timeout'), {
1920+
code: '57014',
1921+
})
1922+
return []
1923+
})
1924+
const reachCounts = () => statements().filter((query) => query.sql.includes(') reached'))
1925+
const budget = () => new SearchBudget('vector', performance.now() + 10_000)
1926+
expect(
1927+
await resolvePermittedDocuments({
1928+
knowledgeBaseIds: ['org-index'],
1929+
access: scope('timed-saturated'),
1930+
budget: budget(),
1931+
})
1932+
).toEqual({ kind: 'unbounded', broad: true })
1933+
expect(reachCounts()).toHaveLength(1)
1934+
/** The next search probes and counts again rather than trusting a reach that was never measured. */
1935+
await resolvePermittedDocuments({
1936+
knowledgeBaseIds: ['org-index'],
1937+
access: scope('timed-saturated'),
1938+
budget: budget(),
1939+
})
1940+
expect(probes()).toBe(2)
1941+
expect(reachCounts()).toHaveLength(2)
1942+
})
1943+
19121944
it('counts a resolved reach against a small index instead of assuming it broad', async () => {
19131945
/** A bound inside the probe limit proves nothing without a saturated probe. */
19141946
dbChainMockFns.execute.mockImplementation(async (query) => {

‎apps/sim/lib/knowledge/search/queries.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1390,10 +1390,11 @@ export async function resolvePermittedDocuments(params: {
13901390
params.accessPlan,
13911391
true
13921392
)
1393+
if (key) saturatedReach.set(key, { broad })
13931394
} catch (error) {
13941395
if (!params.budget?.isTimeout(error)) throw error
1396+
/** A count that ran out of time decides this search only; the next one counts again. */
13951397
}
1396-
if (key) saturatedReach.set(key, { broad })
13971398
}
13981399
}
13991400
const permitted: PermittedDocuments =

‎apps/sim/lib/knowledge/search/tin-keyword.test.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,7 @@ describe('resolveTinKeywordQuery', () => {
3636
it('is off while the rollout flag is off, without touching the database', async () => {
3737
mockIsFeatureEnabled.mockResolvedValue(false)
3838
expect(await resolveTinKeywordQuery(true, 'release notes', 'english', undefined)).toBeNull()
39-
expect(
40-
dbChainMockFns.execute.mock.calls.some(([query]) =>
41-
JSON.stringify(query).includes('websearch_to_tsquery')
42-
)
43-
).toBe(false)
39+
expect(dbChainMockFns.execute).not.toHaveBeenCalled()
4440
})
4541

4642
it('translates the analyzed query when every base is a search index', async () => {

‎apps/sim/lib/knowledge/search/tin-keyword.ts‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,9 @@ export async function resolveTinKeywordQuery(
5252
): Promise<string | null> {
5353
if (!searchIndexOnly) return null
5454
try {
55-
/** The flag and the index are independent facts; the search waits for the slower one only. */
56-
const [enabled, ready] = await Promise.all([
57-
isFeatureEnabled('knowledge-tin-keyword'),
58-
indexReadiness.fetch('index', { context: budget }),
59-
])
60-
if (!enabled || !ready) return null
55+
/** The flag is read from memory and decides whether the index is worth asking about at all. */
56+
if (!(await isFeatureEnabled('knowledge-tin-keyword'))) return null
57+
if (!(await indexReadiness.fetch('index', { context: budget }))) return null
6158
const [{ rendered }] = await runSearchQuery(budget, 'keyword.tin_query', (executor) =>
6259
executor.execute<{ rendered: string }>(
6360
sql`SELECT websearch_to_tsquery(${ftsConfig}::regconfig, ${query})::text AS rendered`

0 commit comments

Comments
 (0)