diff --git a/api/knowledge-fs-contract.lock.json b/api/knowledge-fs-contract.lock.json index 876ee5def94..09a3ff488f6 100644 --- a/api/knowledge-fs-contract.lock.json +++ b/api/knowledge-fs-contract.lock.json @@ -1,6 +1,6 @@ { "schemaVersion": 5, - "subtreeTree": "7f8c4b3b5f6bc8ade3d87bf3100b81c58e254de4", + "subtreeTree": "7475a7b293fa321bc728243a7ba62284bf469883", "openapiSha256": "5f9bee6a3593d8bd05308c7a57ab3d02ef451133cde9347a40543fae934a9a59", "capabilityV2AuthManifestSha256": "e322a2fa779d1f40b95c54c1021cffecaec77abbd7b34899573dcdf4ff353109", "capabilityV2AuthTestVectorSha256": "ae0de37b1ff05c40f905cf17a7b410d8971acacf64db07d5ee3d6fecfa559ce3", diff --git a/knowledge-fs/packages/api/src/source-product-workflow-database-repository.test.ts b/knowledge-fs/packages/api/src/source-product-workflow-database-repository.test.ts index a57be564130..2d63e54f097 100644 --- a/knowledge-fs/packages/api/src/source-product-workflow-database-repository.test.ts +++ b/knowledge-fs/packages/api/src/source-product-workflow-database-repository.test.ts @@ -1996,13 +1996,25 @@ describe("database source-product workflow repository edge coverage", () => { expect(calls[0]).toMatchObject({ maxRows: 2, operation: "select", - params: [tenantId, knowledgeSpaceId, '["team:reader"]', "sync", sourceId, "source-b"], + params: [ + tenantId, + knowledgeSpaceId, + '["team:reader"]', + "sync", + "crawl-import", + "online-document-import", + "online-drive-import", + sourceId, + "source-b", + ], tableName: "source_workflow_runs", }); expect(calls[0]?.sql).toContain("ROW_NUMBER() OVER"); expect(calls[0]?.sql).toContain('CASE WHEN "active_slot" = 1 THEN 1 ELSE 0 END DESC'); expect(calls[0]?.sql).toContain('"source_run_rank" = 1'); - expect(calls[0]?.sql).toContain('"source_id" IN ($5, $6)'); + expect(calls[0]?.sql).toContain('"source_id" IN ($8, $9)'); + expect(calls[0]?.sql).toContain('"kind" IN ($5, $6, $7)'); + expect(calls[0]?.sql).toContain('"active_slot" = 1'); expect(calls[0]?.sql).toContain('"required_permission_scope"'); expect(calls[0]?.sql).toContain('"capability_grants"'); await expect( @@ -2040,6 +2052,9 @@ describe("database source-product workflow repository edge coverage", () => { '["team:reader"]', '["team:reader"]', "sync", + "crawl-import", + "online-document-import", + "online-drive-import", sourceId, ]); const call = calls[0]; diff --git a/knowledge-fs/packages/api/src/source-product-workflow-database-repository.ts b/knowledge-fs/packages/api/src/source-product-workflow-database-repository.ts index 1de5fec74a7..b388064eadb 100644 --- a/knowledge-fs/packages/api/src/source-product-workflow-database-repository.ts +++ b/knowledge-fs/packages/api/src/source-product-workflow-database-repository.ts @@ -1195,8 +1195,13 @@ export function createDatabaseSourceProductWorkflowRepository(input: { params, candidateGrants, ); - params.push("sync"); - const kindPlaceholder = p(database, params.length); + params.push("sync", "crawl-import", "online-document-import", "online-drive-import"); + const syncKindPlaceholder = p(database, params.length - 3); + const importKindPlaceholders = [ + p(database, params.length - 2), + p(database, params.length - 1), + p(database, params.length), + ].join(", "); const placeholders = ids .map((id) => { params.push(id); @@ -1209,7 +1214,7 @@ export function createDatabaseSourceProductWorkflowRepository(input: { maxRows: ids.length, operation: "select", params, - sql: `SELECT * FROM (SELECT ${q(database, runTable)}.*, ROW_NUMBER() OVER (PARTITION BY ${q(database, "source_id")} ORDER BY CASE WHEN ${q(database, "active_slot")} = 1 THEN 1 ELSE 0 END DESC, ${q(database, "created_at")} DESC, ${q(database, "updated_at")} DESC, ${q(database, "id")} DESC) AS ${q(database, rankColumn)} FROM ${q(database, runTable)} WHERE ${q(database, "tenant_id")} = ${p(database, 1)} AND ${q(database, "knowledge_space_id")} = ${p(database, 2)} AND ${permissionScopePredicate} AND ${q(database, "kind")} = ${kindPlaceholder} AND ${q(database, "source_id")} IN (${placeholders})) ${q(database, rankedRuns)} WHERE ${q(database, rankColumn)} = 1;`, + sql: `SELECT * FROM (SELECT ${q(database, runTable)}.*, ROW_NUMBER() OVER (PARTITION BY ${q(database, "source_id")} ORDER BY CASE WHEN ${q(database, "active_slot")} = 1 THEN 1 ELSE 0 END DESC, ${q(database, "created_at")} DESC, ${q(database, "updated_at")} DESC, ${q(database, "id")} DESC) AS ${q(database, rankColumn)} FROM ${q(database, runTable)} WHERE ${q(database, "tenant_id")} = ${p(database, 1)} AND ${q(database, "knowledge_space_id")} = ${p(database, 2)} AND ${permissionScopePredicate} AND (${q(database, "kind")} = ${syncKindPlaceholder} OR (${q(database, "kind")} IN (${importKindPlaceholders}) AND ${q(database, "active_slot")} = 1)) AND ${q(database, "source_id")} IN (${placeholders})) ${q(database, rankedRuns)} WHERE ${q(database, rankColumn)} = 1;`, tableName: runTable, }); return result.rows.map(mapRun); diff --git a/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.test.ts b/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.test.ts index 18dd97b22ae..50451707f4c 100644 --- a/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.test.ts +++ b/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.test.ts @@ -1225,6 +1225,16 @@ describe("in-memory source product workflow repository", () => { : null, }); await repository.start(runRecord("active-sync")); + await repository.start( + runRecord("active-import", { + kind: "crawl-import", + sourceId: "source-import", + }), + ); + await terminalRun(repository, "completed-import", "completed", { + kind: "online-document-import", + sourceId: "source-completed-import", + }); await repository.start( runRecord("other-source", { sourceId: "source-other", @@ -1256,6 +1266,8 @@ describe("in-memory source product workflow repository", () => { sourceIds: [ "source-memory", "source-other", + "source-import", + "source-completed-import", "source-private", "source-capability-private", "source-memory", @@ -1264,6 +1276,7 @@ describe("in-memory source product workflow repository", () => { }), ).resolves.toEqual([ expect.objectContaining({ id: "active-sync", sourceId: "source-memory" }), + expect.objectContaining({ id: "active-import", sourceId: "source-import" }), expect.objectContaining({ id: "other-source", sourceId: "source-other" }), ]); await expect( diff --git a/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.ts b/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.ts index 3b73de39325..5cc2caa3aa5 100644 --- a/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.ts +++ b/knowledge-fs/packages/api/src/source-product-workflow-memory-repository.ts @@ -694,7 +694,13 @@ export function createInMemorySourceProductWorkflowRepository(input?: { run.tenantId !== tenantId || run.knowledgeSpaceId !== knowledgeSpaceId || !runPermissionScopeAllows(run, candidateGrants) || - run.kind !== "sync" || + (run.kind !== "sync" && + !( + run.activeSlot === 1 && + (run.kind === "crawl-import" || + run.kind === "online-document-import" || + run.kind === "online-drive-import") + )) || !run.sourceId || !requestedSourceIds.has(run.sourceId) ) {