@itwin/core-backend 5.15.1 → 5.16.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/lib/cjs/ConcurrentQuery.d.ts +4 -0
- package/lib/cjs/ConcurrentQuery.d.ts.map +1 -1
- package/lib/cjs/ConcurrentQuery.js +28 -1
- package/lib/cjs/ConcurrentQuery.js.map +1 -1
- package/lib/cjs/ECDb.d.ts.map +1 -1
- package/lib/cjs/ECDb.js +5 -10
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/ECSqlRowExecutor.d.ts +39 -55
- package/lib/cjs/ECSqlRowExecutor.d.ts.map +1 -1
- package/lib/cjs/ECSqlRowExecutor.js +118 -140
- package/lib/cjs/ECSqlRowExecutor.js.map +1 -1
- package/lib/cjs/ECSqlSyncReader.d.ts +21 -8
- package/lib/cjs/ECSqlSyncReader.d.ts.map +1 -1
- package/lib/cjs/ECSqlSyncReader.js +67 -25
- package/lib/cjs/ECSqlSyncReader.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +5 -10
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/IModelHost.d.ts +7 -0
- package/lib/cjs/IModelHost.d.ts.map +1 -1
- package/lib/cjs/IModelHost.js +1 -0
- package/lib/cjs/IModelHost.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts.map +1 -1
- package/lib/cjs/TxnManager.js +11 -6
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/internal/ChangesetConflictArgs.d.ts +4 -0
- package/lib/cjs/internal/ChangesetConflictArgs.d.ts.map +1 -1
- package/lib/cjs/internal/ChangesetConflictArgs.js +1 -0
- package/lib/cjs/internal/ChangesetConflictArgs.js.map +1 -1
- package/lib/cjs/internal/QueryMetadataCache.d.ts +8 -0
- package/lib/cjs/internal/QueryMetadataCache.d.ts.map +1 -1
- package/lib/cjs/internal/QueryMetadataCache.js +23 -0
- package/lib/cjs/internal/QueryMetadataCache.js.map +1 -1
- package/lib/esm/ConcurrentQuery.d.ts +4 -0
- package/lib/esm/ConcurrentQuery.d.ts.map +1 -1
- package/lib/esm/ConcurrentQuery.js +29 -2
- package/lib/esm/ConcurrentQuery.js.map +1 -1
- package/lib/esm/ECDb.d.ts.map +1 -1
- package/lib/esm/ECDb.js +6 -11
- package/lib/esm/ECDb.js.map +1 -1
- package/lib/esm/ECSqlRowExecutor.d.ts +39 -55
- package/lib/esm/ECSqlRowExecutor.d.ts.map +1 -1
- package/lib/esm/ECSqlRowExecutor.js +119 -140
- package/lib/esm/ECSqlRowExecutor.js.map +1 -1
- package/lib/esm/ECSqlSyncReader.d.ts +21 -8
- package/lib/esm/ECSqlSyncReader.d.ts.map +1 -1
- package/lib/esm/ECSqlSyncReader.js +68 -26
- package/lib/esm/ECSqlSyncReader.js.map +1 -1
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +6 -11
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/IModelHost.d.ts +7 -0
- package/lib/esm/IModelHost.d.ts.map +1 -1
- package/lib/esm/IModelHost.js +1 -0
- package/lib/esm/IModelHost.js.map +1 -1
- package/lib/esm/TxnManager.d.ts.map +1 -1
- package/lib/esm/TxnManager.js +12 -7
- package/lib/esm/TxnManager.js.map +1 -1
- package/lib/esm/internal/ChangesetConflictArgs.d.ts +4 -0
- package/lib/esm/internal/ChangesetConflictArgs.d.ts.map +1 -1
- package/lib/esm/internal/ChangesetConflictArgs.js +1 -0
- package/lib/esm/internal/ChangesetConflictArgs.js.map +1 -1
- package/lib/esm/internal/QueryMetadataCache.d.ts +8 -0
- package/lib/esm/internal/QueryMetadataCache.d.ts.map +1 -1
- package/lib/esm/internal/QueryMetadataCache.js +23 -0
- package/lib/esm/internal/QueryMetadataCache.js.map +1 -1
- package/lib/esm/test/IModelHost.test.js +103 -2
- package/lib/esm/test/IModelHost.test.js.map +1 -1
- package/lib/esm/test/ecdb/CTE.test.js +21 -0
- package/lib/esm/test/ecdb/CTE.test.js.map +1 -1
- package/lib/esm/test/ecdb/ConcurrentQuery.test.js +72 -0
- package/lib/esm/test/ecdb/ConcurrentQuery.test.js.map +1 -1
- package/lib/esm/test/ecdb/ConcurrentQueryLoad.test.js +51 -9
- package/lib/esm/test/ecdb/ConcurrentQueryLoad.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECSqlQuery.test.js +2 -1
- package/lib/esm/test/ecdb/ECSqlQuery.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECSqlSyncReader.test.js +338 -84
- package/lib/esm/test/ecdb/ECSqlSyncReader.test.js.map +1 -1
- package/lib/esm/test/ecdb/QueryMetadataCache.test.js +40 -4
- package/lib/esm/test/ecdb/QueryMetadataCache.test.js.map +1 -1
- package/lib/esm/test/ecdb/QueryReaders.test.js +14 -7
- package/lib/esm/test/ecdb/QueryReaders.test.js.map +1 -1
- package/lib/esm/test/standalone/ChangeMerge.test.js +71 -1
- package/lib/esm/test/standalone/ChangeMerge.test.js.map +1 -1
- package/lib/esm/test/standalone/IModelWrite.test.js +6 -2
- package/lib/esm/test/standalone/IModelWrite.test.js.map +1 -1
- package/lib/esm/test/standalone/MergeConflict.test.js +15 -0
- package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
- package/package.json +16 -16
|
@@ -161,6 +161,78 @@ describe("ConcurrentQuery", () => {
|
|
|
161
161
|
db.close();
|
|
162
162
|
}
|
|
163
163
|
});
|
|
164
|
+
it("returns primary query responses synchronously, including paging and errors", async () => {
|
|
165
|
+
const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim"));
|
|
166
|
+
try {
|
|
167
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 8388608 } });
|
|
168
|
+
const query = "SELECT ECInstanceId,ECClassId,Model FROM bis.Element ORDER BY ECInstanceId LIMIT 10";
|
|
169
|
+
const request = { query, usePrimaryConn: true, convertClassIdsToClassNames: true };
|
|
170
|
+
const immediate = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], request);
|
|
171
|
+
const wrapped = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], request);
|
|
172
|
+
expect(immediate.status).eq(DbResponseStatus.Done);
|
|
173
|
+
expect(immediate.data).deep.eq(wrapped.data);
|
|
174
|
+
expect(immediate.meta).deep.eq(wrapped.meta);
|
|
175
|
+
expect(immediate.rowCount).eq(wrapped.rowCount);
|
|
176
|
+
expect(immediate.stats.resumed).eq(false);
|
|
177
|
+
const empty = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], { ...request, query: `${query.replace(" ORDER BY ECInstanceId LIMIT 10", "")} WHERE ECInstanceId=0` });
|
|
178
|
+
expect(empty.status).eq(DbResponseStatus.Done);
|
|
179
|
+
expect(empty.data).deep.eq([]);
|
|
180
|
+
expect(empty.meta).deep.eq(immediate.meta);
|
|
181
|
+
expect(() => ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], { query })).to.throw("must use the primary connection");
|
|
182
|
+
const invalid = { query: "SELECT * FROM MissingSchema.MissingClass", usePrimaryConn: true, suppressLogErrors: true };
|
|
183
|
+
const error = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], invalid);
|
|
184
|
+
const wrappedError = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], invalid);
|
|
185
|
+
expect(error.status).greaterThanOrEqual(DbResponseStatus.Error);
|
|
186
|
+
expect(error.status).eq(wrappedError.status);
|
|
187
|
+
expect(error.error).eq(wrappedError.error);
|
|
188
|
+
expect(error.data).deep.eq([]);
|
|
189
|
+
ConcurrentQuery.shutdown(db[_nativeDb]);
|
|
190
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 1 } });
|
|
191
|
+
const first = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], request);
|
|
192
|
+
expect(first.status).eq(DbResponseStatus.Partial);
|
|
193
|
+
expect(first.data.length).eq(1);
|
|
194
|
+
const next = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], { ...request, includeMetaData: false, limit: { offset: 1, count: -1 } });
|
|
195
|
+
expect(next.data).deep.eq([immediate.data[1]]);
|
|
196
|
+
expect(next.meta).deep.eq([]);
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
ConcurrentQuery.resetConfig(db[_nativeDb]);
|
|
200
|
+
db.close();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
it("reads primary query options once during native decoding", () => {
|
|
204
|
+
const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim"));
|
|
205
|
+
try {
|
|
206
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 8388608 } });
|
|
207
|
+
let queryReads = 0, metadataReads = 0, limitReads = 0;
|
|
208
|
+
const request = {
|
|
209
|
+
usePrimaryConn: true,
|
|
210
|
+
get query() {
|
|
211
|
+
++queryReads;
|
|
212
|
+
return "SELECT ECInstanceId FROM bis.Element ORDER BY ECInstanceId";
|
|
213
|
+
},
|
|
214
|
+
get includeMetaData() {
|
|
215
|
+
++metadataReads;
|
|
216
|
+
return true;
|
|
217
|
+
},
|
|
218
|
+
get limit() {
|
|
219
|
+
++limitReads;
|
|
220
|
+
return { count: 1, offset: 0 };
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
const response = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], request);
|
|
224
|
+
expect(response.status).eq(DbResponseStatus.Done);
|
|
225
|
+
expect(response.data.length).eq(1);
|
|
226
|
+
expect(response.meta.length).eq(1);
|
|
227
|
+
expect(queryReads).eq(1);
|
|
228
|
+
expect(metadataReads).eq(1);
|
|
229
|
+
expect(limitReads).eq(1);
|
|
230
|
+
}
|
|
231
|
+
finally {
|
|
232
|
+
ConcurrentQuery.resetConfig(db[_nativeDb]);
|
|
233
|
+
db.close();
|
|
234
|
+
}
|
|
235
|
+
});
|
|
164
236
|
it("time limit check", async () => {
|
|
165
237
|
const testFile = IModelTestUtils.resolveAssetFile("test.bim");
|
|
166
238
|
const db = SnapshotDb.openFile(testFile);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConcurrentQuery.test.js","sourceRoot":"","sources":["../../../../src/test/ecdb/ConcurrentQuery.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { DbQueryRequest, DbQueryResponse, DbResponseStatus, DbValueFormat, QueryBinder } from \"@itwin/core-common\";\r\nimport { expect } from \"chai\";\r\nimport * as os from \"os\";\r\nimport { ConcurrentQuery } from \"../../ConcurrentQuery\";\r\nimport { SnapshotDb } from \"../../IModelDb\";\r\nimport { _nativeDb } from \"../../core-backend\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\n\r\nasync function delay(ms: number): Promise<void> {\r\n return new Promise(resolve => {\r\n setTimeout(resolve, ms);\r\n });\r\n}\r\n\r\n/**\r\n * The native default for `workerThreads` is 4, capped at the machine's hardware concurrency\r\n * (2-core CI agents report 2). An explicit request above hardware concurrency is rejected and\r\n * falls back to that default rather than being clamped.\r\n */\r\nfunction defaultWorkerThreads(): number {\r\n return Math.min(4, os.availableParallelism());\r\n}\r\n\r\ndescribe(\"ConcurrentQuery\", () => {\r\n it(\"default config\", () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const defaultConfig = {\r\n autoShutdownWhenIdleForSeconds: 1800,\r\n doNotUsePrimaryConnToPrepare: false,\r\n globalQuota: { time: 60, memory: 8388608 },\r\n ignoreDelay: true,\r\n ignorePriority: false,\r\n memoryMapFileSize: 0,\r\n monitorPollInterval: 5000,\r\n progressOpCount: 5000,\r\n requestQueueSize: 2000,\r\n statementCacheSizePerWorker: 40,\r\n enableCursors: true,\r\n maxCursorsPerWorker: -1,\r\n cursorIdleTimeout: 30,\r\n workerThreads: defaultWorkerThreads(),\r\n };\r\n const config = ConcurrentQuery.resetConfig(db[_nativeDb], {});\r\n expect(config).deep.eq(defaultConfig);\r\n db.close();\r\n });\r\n\r\n it(\"modify config\", () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const modifiedConfig = {\r\n autoShutdownWhenIdleForSeconds: 100,\r\n doNotUsePrimaryConnToPrepare: true,\r\n globalQuota: { time: 10, memory: 1000000 },\r\n ignoreDelay: false,\r\n ignorePriority: true,\r\n memoryMapFileSize: 100,\r\n monitorPollInterval: 2000,\r\n progressOpCount: 6000,\r\n requestQueueSize: 1000,\r\n statementCacheSizePerWorker: 20,\r\n enableCursors: false,\r\n maxCursorsPerWorker: 3,\r\n cursorIdleTimeout: 10,\r\n workerThreads: 1,\r\n };\r\n const config = ConcurrentQuery.resetConfig(db[_nativeDb], modifiedConfig);\r\n expect(config).deep.eq(modifiedConfig);\r\n db.close();\r\n });\r\n\r\n it(\"workerThreads above hardware concurrency falls back to the default\", () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const requested = os.availableParallelism() + 8;\r\n const config = ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: requested });\r\n expect(config.workerThreads).eq(defaultWorkerThreads());\r\n db.close();\r\n });\r\n\r\n it(\"round-trips the page-cache target in KiB and rejects invalid sizes\", () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n expect(ConcurrentQuery.resetConfig(db[_nativeDb], {}).cacheSizeInKB).eq(undefined);\r\n for (const cacheSizeInKB of [0, 8192, 2147483647])\r\n expect(ConcurrentQuery.resetConfig(db[_nativeDb], { cacheSizeInKB }).cacheSizeInKB).eq(cacheSizeInKB);\r\n for (const cacheSizeInKB of [-1, 1.5, 2147483648, NaN, Infinity, -Infinity])\r\n expect(ConcurrentQuery.resetConfig(db[_nativeDb], { cacheSizeInKB }).cacheSizeInKB).eq(undefined);\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"resumes finite pages without losing rows, with OFFSET fallback when disabled\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n for (const enableCursors of [false, true]) {\r\n ConcurrentQuery.shutdown(db[_nativeDb]);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: 1, enableCursors, globalQuota: { time: 60, memory: 1 } });\r\n const rows: number[] = [];\r\n let resumed = 0;\r\n while (rows.length < 20) {\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], {\r\n query: \"WITH sequence(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM sequence WHERE n<50) SELECT n FROM sequence ORDER BY n DESC\",\r\n cursorId: \"finite-reader\",\r\n limit: { offset: 5 + rows.length, count: 20 - rows.length },\r\n });\r\n expect(resp.status).eq(DbResponseStatus.Partial);\r\n expect(resp.data).deep.eq([[45 - rows.length]]);\r\n rows.push(resp.data[0][0]);\r\n if (resp.stats.resumed)\r\n ++resumed;\r\n }\r\n expect(rows).deep.eq(Array.from({ length: 20 }, (_, i) => 45 - i));\r\n expect(resumed).eq(enableCursors ? 19 : 0);\r\n }\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"isolates readers and bindings and falls back after cursor eviction\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: 1, maxCursorsPerWorker: 1, globalQuota: { time: 60, memory: 1 } });\r\n const query = \"WITH sequence(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM sequence WHERE n<10) SELECT n+? FROM sequence ORDER BY n\";\r\n const page = async (cursorId: string, offset: number, value: number) => ConcurrentQuery.executeQueryRequest(db[_nativeDb], {\r\n query, cursorId, args: new QueryBinder().bindInt(1, value).serialize(), limit: { offset, count: -1 },\r\n });\r\n expect((await page(\"a\", 0, 0)).data).deep.eq([[1]]);\r\n expect((await page(\"a\", 1, 0)).stats.resumed).eq(true);\r\n expect((await page(\"b\", 0, 100)).data).deep.eq([[101]]);\r\n const evicted = await page(\"a\", 2, 0);\r\n expect(evicted.stats.resumed).eq(false);\r\n expect(evicted.data).deep.eq([[3]]);\r\n const rebound = await page(\"a\", 3, 100);\r\n expect(rebound.stats.resumed).eq(false);\r\n expect(rebound.data).deep.eq([[104]]);\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"preserves class and navigation rendering across worker connections\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: defaultWorkerThreads(), globalQuota: { time: 60, memory: 8388608 } });\r\n const query = \"SELECT ECClassId, Schema FROM meta.ECClassDef ORDER BY ECInstanceId LIMIT 20\";\r\n for (const valueFormat of [DbValueFormat.ECSqlNames, DbValueFormat.JsNames]) {\r\n const request: DbQueryRequest = {\r\n query, valueFormat,\r\n convertClassIdsToClassNames: true,\r\n };\r\n const primary = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], { ...request, usePrimaryConn: true });\r\n expect(primary.status).eq(DbResponseStatus.Done);\r\n expect(primary.data.length).eq(20);\r\n const workers = await Promise.all(Array.from({ length: defaultWorkerThreads() * 2 },\r\n async () => ConcurrentQuery.executeQueryRequest(db[_nativeDb], request)));\r\n for (const worker of workers) {\r\n expect(worker.status).eq(DbResponseStatus.Done);\r\n expect(worker.data).deep.eq(primary.data);\r\n expect(worker.meta).deep.eq(primary.meta);\r\n }\r\n }\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"time limit check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 1, memory: 100000 }, progressOpCount: 1000 });\r\n // await runSingleRequest(db, `SELECT 1`);\r\n const req: DbQueryRequest = {\r\n query: `WITH sequence(n,k) AS (\r\n SELECT 1,1 UNION ALL SELECT n + 1, random() FROM sequence WHERE n < 10000000\r\n ) SELECT COUNT(*) FROM sequence s`\r\n };\r\n\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], req);\r\n expect(resp.status).equals(DbResponseStatus.Partial);\r\n expect(resp.stats.timeLimit).equals(1000);\r\n expect(resp.stats.memLimit).equals(100000);\r\n expect(resp.stats.cpuTime).to.be.closeTo(1000970, 500000);\r\n expect(resp.stats.totalTime).to.be.closeTo(1001, 100);\r\n expect(resp.stats.memUsed).to.be.closeTo(2, 3);\r\n // prepareTime varies on CI: the first query prepares against the (cold) shared schema-source\r\n // connection, so assert only that it is negligible relative to the ~1000ms execution rather than\r\n // pinning it to a tight tolerance (which flakes -- e.g. observed 7ms against a 0 +/- 4 bound).\r\n expect(resp.stats.prepareTime).to.be.lessThan(100);\r\n db.close();\r\n });\r\n\r\n it(\"memory limit check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 1000 }, progressOpCount: 1000 });\r\n // await runSingleRequest(db, `SELECT 1`);\r\n const req: DbQueryRequest = {\r\n query: `WITH sequence(n) AS (\r\n SELECT 1\r\n UNION ALL\r\n SELECT n + 1 FROM sequence WHERE n < 10000000\r\n )\r\n SELECT 'xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx' FROM sequence s`\r\n };\r\n\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], req);\r\n expect(resp.status).equals(DbResponseStatus.Partial);\r\n expect(resp.stats.timeLimit).equals(60000);\r\n expect(resp.stats.memLimit).equals(1000);\r\n expect(resp.stats.memUsed).to.be.closeTo(1037, 100);\r\n db.close();\r\n });\r\n\r\n it(\"prepare error\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const req: DbQueryRequest = {\r\n query: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`\r\n };\r\n\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], req);\r\n expect(resp.status).equals(DbResponseStatus.Error_ECSql_PreparedFailed);\r\n db.close();\r\n });\r\n\r\n it.skip(\"restart query #flaky\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 10000000 }, progressOpCount: 1000 });\r\n const req0: DbQueryRequest = {\r\n query: `WITH sequence(n) AS (\r\n SELECT 1 UNION ALL SELECT n + 1 FROM sequence WHERE n < 10000000\r\n ) SELECT n FROM sequence s`,\r\n restartToken: \"Blah\",\r\n };\r\n\r\n const req1: DbQueryRequest = {\r\n query: `WITH sequence(n) AS (\r\n SELECT 1 UNION ALL SELECT n + 1 FROM sequence WHERE n < 1000\r\n ) SELECT n FROM sequence s`,\r\n restartToken: \"Blah\",\r\n };\r\n\r\n const resp1 = ConcurrentQuery.executeQueryRequest(db[_nativeDb], req0);\r\n await delay(1);\r\n const resp2 = ConcurrentQuery.executeQueryRequest(db[_nativeDb], req1);\r\n const resp = await Promise.all([resp1, resp2]);\r\n expect(resp[0].status).equals(DbResponseStatus.Cancel); // can result in DbResponseStatus.Partial instead of DbResponseStatus.Cancel\r\n expect(resp[1].status).equals(DbResponseStatus.Done);\r\n db.close();\r\n });\r\n\r\n it(\"queue limit check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n try {\r\n const requestQueueSize = 40;\r\n const requestCount = 60;\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { requestQueueSize, ignoreDelay: false, globalQuota: { time: 5, memory: 100000 } });\r\n // A delay keeps accepted requests in the queue (workers only dequeue requests whose delay has elapsed),\r\n // so the queue fills up deterministically regardless of how fast the worker threads are.\r\n const req: DbQueryRequest = { query: \"SELECT 1\", delay: 2000 };\r\n\r\n const responsePromises: Promise<DbQueryResponse>[] = [];\r\n for (let i = 0; i < requestCount; ++i) {\r\n responsePromises.push(ConcurrentQuery.executeQueryRequest(db[_nativeDb], req));\r\n }\r\n const responses = await Promise.all(responsePromises);\r\n const queueFullResponses = responses.filter((x) => x.status === DbResponseStatus.QueueFull);\r\n expect(queueFullResponses.length).to.equal(requestCount - requestQueueSize);\r\n const otherStatuses = responses.filter((x) => x.status !== DbResponseStatus.QueueFull).map((x) => x.status);\r\n expect(otherStatuses).to.have.lengthOf(requestQueueSize);\r\n expect(otherStatuses.every((x) => x === DbResponseStatus.Done)).to.be.true;\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"timeout check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { ignoreDelay: false, monitorPollInterval: 1000, globalQuota: { time: 1, memory: 1000 } });\r\n // Keep requests queued past their deadline without generating large result sets.\r\n const req: DbQueryRequest = { query: \"SELECT 1\", delay: 2000 };\r\n const responsePromises: Promise<DbQueryResponse>[] = [];\r\n for (let i = 0; i < 100; ++i) {\r\n responsePromises.push(ConcurrentQuery.executeQueryRequest(db[_nativeDb], req));\r\n }\r\n const responses = await Promise.all(responsePromises);\r\n for (const response of responses)\r\n expect(response.status).equals(DbResponseStatus.Timeout);\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"should handle concurrent queries during shutdown without deadlock\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const iModelDb = SnapshotDb.openFile(testFile);\r\n // Configure for maximum contention\r\n const config = {\r\n requestQueueSize: 1000,\r\n statementCacheSizePerWorker: 1, // Force frequent prepare calls\r\n ignoreDelay: false, // Honor request delays so some requests are guaranteed to still be queued at shutdown\r\n };\r\n\r\n // Reset configuration\r\n ConcurrentQuery.resetConfig(iModelDb[_nativeDb], config);\r\n\r\n // Requests that are still queued when shutdown happens are rejected with ShuttingDown. A delay keeps these\r\n // requests from being dequeued by a worker, so they are deterministically queued at shutdown regardless of\r\n // how fast or slow the worker threads are. They are enqueued first so they cannot be rejected with QueueFull.\r\n const queuedRequestCount = 10;\r\n const queuedPromises: Promise<DbQueryResponse>[] = [];\r\n for (let i = 0; i < queuedRequestCount; ++i) {\r\n queuedPromises.push(ConcurrentQuery.executeQueryRequest(iModelDb[_nativeDb], { query: \"SELECT 1\", delay: 5000 }));\r\n }\r\n\r\n const responsePromises: Promise<DbQueryResponse>[] = [];\r\n const spamPromises: Promise<void>[] = [];\r\n let shouldStop = false;\r\n\r\n const spam = async () => {\r\n while (!shouldStop) {\r\n // Use random numbers to prevent query caching\r\n const query = `\r\n WITH sequence(n,k) AS (\r\n SELECT 1,1 UNION ALL SELECT n + 1, random() FROM sequence WHERE n < 10000000\r\n ) SELECT COUNT(*) FROM sequence s\r\n `;\r\n const request: DbQueryRequest = { query };\r\n const p = ConcurrentQuery.executeQueryRequest(iModelDb[_nativeDb], request);\r\n responsePromises.push(p);\r\n await new Promise(resolve => setImmediate(resolve));\r\n }\r\n };\r\n\r\n // Start spamming simple queries to increase contention\r\n spamPromises.push(spam());\r\n // Let queries start and establish contention\r\n await new Promise(resolve => setTimeout(resolve, 10));\r\n\r\n ConcurrentQuery.shutdown(iModelDb[_nativeDb]);\r\n\r\n shouldStop = true;\r\n\r\n // Wait for all promises to complete. If shutdown deadlocked, these would never settle and the test would time out.\r\n const queuedResults = await Promise.allSettled(queuedPromises);\r\n const results = await Promise.allSettled(responsePromises);\r\n await Promise.allSettled(spamPromises);\r\n\r\n expect(results.every((result) => result.status === \"fulfilled\")).to.be.true;\r\n // Every request that was still queued at shutdown must be rejected with ShuttingDown.\r\n const queuedStatuses = queuedResults.map((result) => result.status === \"fulfilled\" ? result.value.status : undefined);\r\n expect(queuedStatuses).to.deep.equal(new Array(queuedRequestCount).fill(DbResponseStatus.ShuttingDown));\r\n\r\n // Restore original config by resetting to default\r\n ConcurrentQuery.resetConfig(iModelDb[_nativeDb], {});\r\n iModelDb.close();\r\n });\r\n});\r\n"]}
|
|
1
|
+
{"version":3,"file":"ConcurrentQuery.test.js","sourceRoot":"","sources":["../../../../src/test/ecdb/ConcurrentQuery.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { DbQueryRequest, DbQueryResponse, DbResponseStatus, DbValueFormat, QueryBinder } from \"@itwin/core-common\";\r\nimport { expect } from \"chai\";\r\nimport * as os from \"os\";\r\nimport { ConcurrentQuery } from \"../../ConcurrentQuery\";\r\nimport { SnapshotDb } from \"../../IModelDb\";\r\nimport { _nativeDb } from \"../../core-backend\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\n\r\nasync function delay(ms: number): Promise<void> {\r\n return new Promise(resolve => {\r\n setTimeout(resolve, ms);\r\n });\r\n}\r\n\r\n/**\r\n * The native default for `workerThreads` is 4, capped at the machine's hardware concurrency\r\n * (2-core CI agents report 2). An explicit request above hardware concurrency is rejected and\r\n * falls back to that default rather than being clamped.\r\n */\r\nfunction defaultWorkerThreads(): number {\r\n return Math.min(4, os.availableParallelism());\r\n}\r\n\r\ndescribe(\"ConcurrentQuery\", () => {\r\n it(\"default config\", () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const defaultConfig = {\r\n autoShutdownWhenIdleForSeconds: 1800,\r\n doNotUsePrimaryConnToPrepare: false,\r\n globalQuota: { time: 60, memory: 8388608 },\r\n ignoreDelay: true,\r\n ignorePriority: false,\r\n memoryMapFileSize: 0,\r\n monitorPollInterval: 5000,\r\n progressOpCount: 5000,\r\n requestQueueSize: 2000,\r\n statementCacheSizePerWorker: 40,\r\n enableCursors: true,\r\n maxCursorsPerWorker: -1,\r\n cursorIdleTimeout: 30,\r\n workerThreads: defaultWorkerThreads(),\r\n };\r\n const config = ConcurrentQuery.resetConfig(db[_nativeDb], {});\r\n expect(config).deep.eq(defaultConfig);\r\n db.close();\r\n });\r\n\r\n it(\"modify config\", () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const modifiedConfig = {\r\n autoShutdownWhenIdleForSeconds: 100,\r\n doNotUsePrimaryConnToPrepare: true,\r\n globalQuota: { time: 10, memory: 1000000 },\r\n ignoreDelay: false,\r\n ignorePriority: true,\r\n memoryMapFileSize: 100,\r\n monitorPollInterval: 2000,\r\n progressOpCount: 6000,\r\n requestQueueSize: 1000,\r\n statementCacheSizePerWorker: 20,\r\n enableCursors: false,\r\n maxCursorsPerWorker: 3,\r\n cursorIdleTimeout: 10,\r\n workerThreads: 1,\r\n };\r\n const config = ConcurrentQuery.resetConfig(db[_nativeDb], modifiedConfig);\r\n expect(config).deep.eq(modifiedConfig);\r\n db.close();\r\n });\r\n\r\n it(\"workerThreads above hardware concurrency falls back to the default\", () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const requested = os.availableParallelism() + 8;\r\n const config = ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: requested });\r\n expect(config.workerThreads).eq(defaultWorkerThreads());\r\n db.close();\r\n });\r\n\r\n it(\"round-trips the page-cache target in KiB and rejects invalid sizes\", () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n expect(ConcurrentQuery.resetConfig(db[_nativeDb], {}).cacheSizeInKB).eq(undefined);\r\n for (const cacheSizeInKB of [0, 8192, 2147483647])\r\n expect(ConcurrentQuery.resetConfig(db[_nativeDb], { cacheSizeInKB }).cacheSizeInKB).eq(cacheSizeInKB);\r\n for (const cacheSizeInKB of [-1, 1.5, 2147483648, NaN, Infinity, -Infinity])\r\n expect(ConcurrentQuery.resetConfig(db[_nativeDb], { cacheSizeInKB }).cacheSizeInKB).eq(undefined);\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"resumes finite pages without losing rows, with OFFSET fallback when disabled\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n for (const enableCursors of [false, true]) {\r\n ConcurrentQuery.shutdown(db[_nativeDb]);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: 1, enableCursors, globalQuota: { time: 60, memory: 1 } });\r\n const rows: number[] = [];\r\n let resumed = 0;\r\n while (rows.length < 20) {\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], {\r\n query: \"WITH sequence(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM sequence WHERE n<50) SELECT n FROM sequence ORDER BY n DESC\",\r\n cursorId: \"finite-reader\",\r\n limit: { offset: 5 + rows.length, count: 20 - rows.length },\r\n });\r\n expect(resp.status).eq(DbResponseStatus.Partial);\r\n expect(resp.data).deep.eq([[45 - rows.length]]);\r\n rows.push(resp.data[0][0]);\r\n if (resp.stats.resumed)\r\n ++resumed;\r\n }\r\n expect(rows).deep.eq(Array.from({ length: 20 }, (_, i) => 45 - i));\r\n expect(resumed).eq(enableCursors ? 19 : 0);\r\n }\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"isolates readers and bindings and falls back after cursor eviction\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: 1, maxCursorsPerWorker: 1, globalQuota: { time: 60, memory: 1 } });\r\n const query = \"WITH sequence(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM sequence WHERE n<10) SELECT n+? FROM sequence ORDER BY n\";\r\n const page = async (cursorId: string, offset: number, value: number) => ConcurrentQuery.executeQueryRequest(db[_nativeDb], {\r\n query, cursorId, args: new QueryBinder().bindInt(1, value).serialize(), limit: { offset, count: -1 },\r\n });\r\n expect((await page(\"a\", 0, 0)).data).deep.eq([[1]]);\r\n expect((await page(\"a\", 1, 0)).stats.resumed).eq(true);\r\n expect((await page(\"b\", 0, 100)).data).deep.eq([[101]]);\r\n const evicted = await page(\"a\", 2, 0);\r\n expect(evicted.stats.resumed).eq(false);\r\n expect(evicted.data).deep.eq([[3]]);\r\n const rebound = await page(\"a\", 3, 100);\r\n expect(rebound.stats.resumed).eq(false);\r\n expect(rebound.data).deep.eq([[104]]);\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"preserves class and navigation rendering across worker connections\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: defaultWorkerThreads(), globalQuota: { time: 60, memory: 8388608 } });\r\n const query = \"SELECT ECClassId, Schema FROM meta.ECClassDef ORDER BY ECInstanceId LIMIT 20\";\r\n for (const valueFormat of [DbValueFormat.ECSqlNames, DbValueFormat.JsNames]) {\r\n const request: DbQueryRequest = {\r\n query, valueFormat,\r\n convertClassIdsToClassNames: true,\r\n };\r\n const primary = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], { ...request, usePrimaryConn: true });\r\n expect(primary.status).eq(DbResponseStatus.Done);\r\n expect(primary.data.length).eq(20);\r\n const workers = await Promise.all(Array.from({ length: defaultWorkerThreads() * 2 },\r\n async () => ConcurrentQuery.executeQueryRequest(db[_nativeDb], request)));\r\n for (const worker of workers) {\r\n expect(worker.status).eq(DbResponseStatus.Done);\r\n expect(worker.data).deep.eq(primary.data);\r\n expect(worker.meta).deep.eq(primary.meta);\r\n }\r\n }\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"returns primary query responses synchronously, including paging and errors\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 8388608 } });\r\n const query = \"SELECT ECInstanceId,ECClassId,Model FROM bis.Element ORDER BY ECInstanceId LIMIT 10\";\r\n const request: DbQueryRequest = { query, usePrimaryConn: true, convertClassIdsToClassNames: true };\r\n const immediate = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], request);\r\n const wrapped = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], request);\r\n expect(immediate.status).eq(DbResponseStatus.Done);\r\n expect(immediate.data).deep.eq(wrapped.data);\r\n expect(immediate.meta).deep.eq(wrapped.meta);\r\n expect(immediate.rowCount).eq(wrapped.rowCount);\r\n expect(immediate.stats.resumed).eq(false);\r\n const empty = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], { ...request, query: `${query.replace(\" ORDER BY ECInstanceId LIMIT 10\", \"\")} WHERE ECInstanceId=0` });\r\n expect(empty.status).eq(DbResponseStatus.Done);\r\n expect(empty.data).deep.eq([]);\r\n expect(empty.meta).deep.eq(immediate.meta);\r\n expect(() => ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], { query })).to.throw(\"must use the primary connection\");\r\n const invalid: DbQueryRequest = { query: \"SELECT * FROM MissingSchema.MissingClass\", usePrimaryConn: true, suppressLogErrors: true };\r\n const error = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], invalid);\r\n const wrappedError = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], invalid);\r\n expect(error.status).greaterThanOrEqual(DbResponseStatus.Error);\r\n expect(error.status).eq(wrappedError.status);\r\n expect(error.error).eq(wrappedError.error);\r\n expect(error.data).deep.eq([]);\r\n\r\n ConcurrentQuery.shutdown(db[_nativeDb]);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 1 } });\r\n const first = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], request);\r\n expect(first.status).eq(DbResponseStatus.Partial);\r\n expect(first.data.length).eq(1);\r\n const next = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], { ...request, includeMetaData: false, limit: { offset: 1, count: -1 } });\r\n expect(next.data).deep.eq([immediate.data[1]]);\r\n expect(next.meta).deep.eq([]);\r\n } finally {\r\n ConcurrentQuery.resetConfig(db[_nativeDb]);\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"reads primary query options once during native decoding\", () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 8388608 } });\r\n let queryReads = 0, metadataReads = 0, limitReads = 0;\r\n const request: DbQueryRequest = {\r\n usePrimaryConn: true,\r\n get query() {\r\n ++queryReads;\r\n return \"SELECT ECInstanceId FROM bis.Element ORDER BY ECInstanceId\";\r\n },\r\n get includeMetaData() {\r\n ++metadataReads;\r\n return true;\r\n },\r\n get limit() {\r\n ++limitReads;\r\n return { count: 1, offset: 0 };\r\n },\r\n };\r\n const response = ConcurrentQuery.executePrimaryQueryRequest(db[_nativeDb], request);\r\n expect(response.status).eq(DbResponseStatus.Done);\r\n expect(response.data.length).eq(1);\r\n expect(response.meta.length).eq(1);\r\n expect(queryReads).eq(1);\r\n expect(metadataReads).eq(1);\r\n expect(limitReads).eq(1);\r\n } finally {\r\n ConcurrentQuery.resetConfig(db[_nativeDb]);\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"time limit check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 1, memory: 100000 }, progressOpCount: 1000 });\r\n // await runSingleRequest(db, `SELECT 1`);\r\n const req: DbQueryRequest = {\r\n query: `WITH sequence(n,k) AS (\r\n SELECT 1,1 UNION ALL SELECT n + 1, random() FROM sequence WHERE n < 10000000\r\n ) SELECT COUNT(*) FROM sequence s`\r\n };\r\n\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], req);\r\n expect(resp.status).equals(DbResponseStatus.Partial);\r\n expect(resp.stats.timeLimit).equals(1000);\r\n expect(resp.stats.memLimit).equals(100000);\r\n expect(resp.stats.cpuTime).to.be.closeTo(1000970, 500000);\r\n expect(resp.stats.totalTime).to.be.closeTo(1001, 100);\r\n expect(resp.stats.memUsed).to.be.closeTo(2, 3);\r\n // prepareTime varies on CI: the first query prepares against the (cold) shared schema-source\r\n // connection, so assert only that it is negligible relative to the ~1000ms execution rather than\r\n // pinning it to a tight tolerance (which flakes -- e.g. observed 7ms against a 0 +/- 4 bound).\r\n expect(resp.stats.prepareTime).to.be.lessThan(100);\r\n db.close();\r\n });\r\n\r\n it(\"memory limit check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 1000 }, progressOpCount: 1000 });\r\n // await runSingleRequest(db, `SELECT 1`);\r\n const req: DbQueryRequest = {\r\n query: `WITH sequence(n) AS (\r\n SELECT 1\r\n UNION ALL\r\n SELECT n + 1 FROM sequence WHERE n < 10000000\r\n )\r\n SELECT 'xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx' FROM sequence s`\r\n };\r\n\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], req);\r\n expect(resp.status).equals(DbResponseStatus.Partial);\r\n expect(resp.stats.timeLimit).equals(60000);\r\n expect(resp.stats.memLimit).equals(1000);\r\n expect(resp.stats.memUsed).to.be.closeTo(1037, 100);\r\n db.close();\r\n });\r\n\r\n it(\"prepare error\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n const req: DbQueryRequest = {\r\n query: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`\r\n };\r\n\r\n const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], req);\r\n expect(resp.status).equals(DbResponseStatus.Error_ECSql_PreparedFailed);\r\n db.close();\r\n });\r\n\r\n it.skip(\"restart query #flaky\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { globalQuota: { time: 60, memory: 10000000 }, progressOpCount: 1000 });\r\n const req0: DbQueryRequest = {\r\n query: `WITH sequence(n) AS (\r\n SELECT 1 UNION ALL SELECT n + 1 FROM sequence WHERE n < 10000000\r\n ) SELECT n FROM sequence s`,\r\n restartToken: \"Blah\",\r\n };\r\n\r\n const req1: DbQueryRequest = {\r\n query: `WITH sequence(n) AS (\r\n SELECT 1 UNION ALL SELECT n + 1 FROM sequence WHERE n < 1000\r\n ) SELECT n FROM sequence s`,\r\n restartToken: \"Blah\",\r\n };\r\n\r\n const resp1 = ConcurrentQuery.executeQueryRequest(db[_nativeDb], req0);\r\n await delay(1);\r\n const resp2 = ConcurrentQuery.executeQueryRequest(db[_nativeDb], req1);\r\n const resp = await Promise.all([resp1, resp2]);\r\n expect(resp[0].status).equals(DbResponseStatus.Cancel); // can result in DbResponseStatus.Partial instead of DbResponseStatus.Cancel\r\n expect(resp[1].status).equals(DbResponseStatus.Done);\r\n db.close();\r\n });\r\n\r\n it(\"queue limit check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n try {\r\n const requestQueueSize = 40;\r\n const requestCount = 60;\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { requestQueueSize, ignoreDelay: false, globalQuota: { time: 5, memory: 100000 } });\r\n // A delay keeps accepted requests in the queue (workers only dequeue requests whose delay has elapsed),\r\n // so the queue fills up deterministically regardless of how fast the worker threads are.\r\n const req: DbQueryRequest = { query: \"SELECT 1\", delay: 2000 };\r\n\r\n const responsePromises: Promise<DbQueryResponse>[] = [];\r\n for (let i = 0; i < requestCount; ++i) {\r\n responsePromises.push(ConcurrentQuery.executeQueryRequest(db[_nativeDb], req));\r\n }\r\n const responses = await Promise.all(responsePromises);\r\n const queueFullResponses = responses.filter((x) => x.status === DbResponseStatus.QueueFull);\r\n expect(queueFullResponses.length).to.equal(requestCount - requestQueueSize);\r\n const otherStatuses = responses.filter((x) => x.status !== DbResponseStatus.QueueFull).map((x) => x.status);\r\n expect(otherStatuses).to.have.lengthOf(requestQueueSize);\r\n expect(otherStatuses.every((x) => x === DbResponseStatus.Done)).to.be.true;\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"timeout check\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(testFile);\r\n try {\r\n ConcurrentQuery.resetConfig(db[_nativeDb], { ignoreDelay: false, monitorPollInterval: 1000, globalQuota: { time: 1, memory: 1000 } });\r\n // Keep requests queued past their deadline without generating large result sets.\r\n const req: DbQueryRequest = { query: \"SELECT 1\", delay: 2000 };\r\n const responsePromises: Promise<DbQueryResponse>[] = [];\r\n for (let i = 0; i < 100; ++i) {\r\n responsePromises.push(ConcurrentQuery.executeQueryRequest(db[_nativeDb], req));\r\n }\r\n const responses = await Promise.all(responsePromises);\r\n for (const response of responses)\r\n expect(response.status).equals(DbResponseStatus.Timeout);\r\n } finally {\r\n db.close();\r\n }\r\n });\r\n\r\n it(\"should handle concurrent queries during shutdown without deadlock\", async () => {\r\n const testFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const iModelDb = SnapshotDb.openFile(testFile);\r\n // Configure for maximum contention\r\n const config = {\r\n requestQueueSize: 1000,\r\n statementCacheSizePerWorker: 1, // Force frequent prepare calls\r\n ignoreDelay: false, // Honor request delays so some requests are guaranteed to still be queued at shutdown\r\n };\r\n\r\n // Reset configuration\r\n ConcurrentQuery.resetConfig(iModelDb[_nativeDb], config);\r\n\r\n // Requests that are still queued when shutdown happens are rejected with ShuttingDown. A delay keeps these\r\n // requests from being dequeued by a worker, so they are deterministically queued at shutdown regardless of\r\n // how fast or slow the worker threads are. They are enqueued first so they cannot be rejected with QueueFull.\r\n const queuedRequestCount = 10;\r\n const queuedPromises: Promise<DbQueryResponse>[] = [];\r\n for (let i = 0; i < queuedRequestCount; ++i) {\r\n queuedPromises.push(ConcurrentQuery.executeQueryRequest(iModelDb[_nativeDb], { query: \"SELECT 1\", delay: 5000 }));\r\n }\r\n\r\n const responsePromises: Promise<DbQueryResponse>[] = [];\r\n const spamPromises: Promise<void>[] = [];\r\n let shouldStop = false;\r\n\r\n const spam = async () => {\r\n while (!shouldStop) {\r\n // Use random numbers to prevent query caching\r\n const query = `\r\n WITH sequence(n,k) AS (\r\n SELECT 1,1 UNION ALL SELECT n + 1, random() FROM sequence WHERE n < 10000000\r\n ) SELECT COUNT(*) FROM sequence s\r\n `;\r\n const request: DbQueryRequest = { query };\r\n const p = ConcurrentQuery.executeQueryRequest(iModelDb[_nativeDb], request);\r\n responsePromises.push(p);\r\n await new Promise(resolve => setImmediate(resolve));\r\n }\r\n };\r\n\r\n // Start spamming simple queries to increase contention\r\n spamPromises.push(spam());\r\n // Let queries start and establish contention\r\n await new Promise(resolve => setTimeout(resolve, 10));\r\n\r\n ConcurrentQuery.shutdown(iModelDb[_nativeDb]);\r\n\r\n shouldStop = true;\r\n\r\n // Wait for all promises to complete. If shutdown deadlocked, these would never settle and the test would time out.\r\n const queuedResults = await Promise.allSettled(queuedPromises);\r\n const results = await Promise.allSettled(responsePromises);\r\n await Promise.allSettled(spamPromises);\r\n\r\n expect(results.every((result) => result.status === \"fulfilled\")).to.be.true;\r\n // Every request that was still queued at shutdown must be rejected with ShuttingDown.\r\n const queuedStatuses = queuedResults.map((result) => result.status === \"fulfilled\" ? result.value.status : undefined);\r\n expect(queuedStatuses).to.deep.equal(new Array(queuedRequestCount).fill(DbResponseStatus.ShuttingDown));\r\n\r\n // Restore original config by resetting to default\r\n ConcurrentQuery.resetConfig(iModelDb[_nativeDb], {});\r\n iModelDb.close();\r\n });\r\n});\r\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Logger, LogLevel, StopWatch } from "@itwin/core-bentley";
|
|
2
2
|
import { expect } from "chai";
|
|
3
|
+
import * as sinon from "sinon";
|
|
3
4
|
import { ConcurrentQuery } from "../../ConcurrentQuery";
|
|
4
5
|
import { SnapshotDb } from "../../IModelDb";
|
|
5
6
|
import { _nativeDb } from "../../core-backend";
|
|
@@ -61,29 +62,29 @@ class LoadSimulator {
|
|
|
61
62
|
});
|
|
62
63
|
const errorCount = errors.length;
|
|
63
64
|
let backendCpuTime = BigInt(0);
|
|
64
|
-
let backendTotalTime =
|
|
65
|
+
let backendTotalTime = 0;
|
|
65
66
|
let backendMemUsed = BigInt(0);
|
|
66
67
|
let backendRowsReturned = BigInt(0);
|
|
67
|
-
let totalTime =
|
|
68
|
+
let totalTime = 0;
|
|
68
69
|
let retryCount = BigInt(0);
|
|
69
|
-
let prepareTime =
|
|
70
|
+
let prepareTime = 0;
|
|
70
71
|
// Calculate average
|
|
71
72
|
results.forEach((r) => {
|
|
72
73
|
backendCpuTime += BigInt(r.stats.backendCpuTime);
|
|
73
|
-
backendTotalTime +=
|
|
74
|
+
backendTotalTime += r.stats.backendTotalTime;
|
|
74
75
|
backendMemUsed += BigInt(r.stats.backendMemUsed);
|
|
75
76
|
backendRowsReturned += BigInt(r.stats.backendRowsReturned);
|
|
76
|
-
totalTime +=
|
|
77
|
+
totalTime += r.stats.totalTime;
|
|
77
78
|
retryCount += BigInt(r.stats.retryCount);
|
|
78
|
-
prepareTime +=
|
|
79
|
+
prepareTime += r.stats.prepareTime;
|
|
79
80
|
});
|
|
80
81
|
backendCpuTime /= BigInt(results.length);
|
|
81
|
-
backendTotalTime /=
|
|
82
|
+
backendTotalTime /= results.length;
|
|
82
83
|
backendMemUsed /= BigInt(results.length);
|
|
83
84
|
backendRowsReturned /= BigInt(results.length);
|
|
84
|
-
totalTime /=
|
|
85
|
+
totalTime /= results.length;
|
|
85
86
|
retryCount /= BigInt(results.length);
|
|
86
|
-
// prepareTime /=
|
|
87
|
+
// prepareTime /= results.length;
|
|
87
88
|
return {
|
|
88
89
|
result: {
|
|
89
90
|
backendCpuTime,
|
|
@@ -101,6 +102,47 @@ class LoadSimulator {
|
|
|
101
102
|
};
|
|
102
103
|
}
|
|
103
104
|
}
|
|
105
|
+
describe("ConcurrentQueryLoad statistics", () => {
|
|
106
|
+
it("preserves fractional timing averages and preparation totals", async () => {
|
|
107
|
+
const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim"));
|
|
108
|
+
const sandbox = sinon.createSandbox();
|
|
109
|
+
try {
|
|
110
|
+
let queryIndex = 0;
|
|
111
|
+
const simulator = new LoadSimulator(db, {
|
|
112
|
+
name: "fractional timings",
|
|
113
|
+
totalBatches: 1,
|
|
114
|
+
taskPerBatch: 2,
|
|
115
|
+
createReader: () => {
|
|
116
|
+
const reader = db.createQueryReader("SELECT 1");
|
|
117
|
+
const timing = ++queryIndex === 1 ? 0.25 : 0.5;
|
|
118
|
+
sandbox.stub(reader, "step").resolves(false);
|
|
119
|
+
sandbox.stub(reader, "stats").get(() => ({
|
|
120
|
+
backendCpuTime: 10,
|
|
121
|
+
backendTotalTime: timing,
|
|
122
|
+
backendMemUsed: 20,
|
|
123
|
+
backendRowsReturned: 1,
|
|
124
|
+
totalTime: timing * 2,
|
|
125
|
+
retryCount: 0,
|
|
126
|
+
prepareTime: timing,
|
|
127
|
+
}));
|
|
128
|
+
return reader;
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
const result = await simulator.run();
|
|
132
|
+
expect(result.errorCount).to.equal(0);
|
|
133
|
+
expect(result.totalQueries).to.equal(2);
|
|
134
|
+
expect(result.result.backendTotalTime).to.equal(0.375);
|
|
135
|
+
expect(result.result.totalTime).to.equal(0.75);
|
|
136
|
+
expect(result.result.prepareTime).to.equal(0.75);
|
|
137
|
+
expect(result.result.backendCpuTime).to.equal(10n);
|
|
138
|
+
expect(result.result.backendRowsReturned).to.equal(1n);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
sandbox.restore();
|
|
142
|
+
db.close();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|
|
104
146
|
describe.skip("ConcurrentQueryLoad", () => {
|
|
105
147
|
it("should run", async () => {
|
|
106
148
|
Logger.initializeToConsole();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConcurrentQueryLoad.test.js","sourceRoot":"","sources":["../../../../src/test/ecdb/ConcurrentQueryLoad.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger, LogLevel, StopWatch } from \"@itwin/core-bentley\";\r\nimport { DbQueryConfig, ECSqlReader, QueryStats } from \"@itwin/core-common\";\r\nimport { expect } from \"chai\";\r\nimport { ConcurrentQuery } from \"../../ConcurrentQuery\";\r\nimport { ECDb } from \"../../ECDb\";\r\nimport { IModelDb, SnapshotDb } from \"../../IModelDb\";\r\nimport { _nativeDb } from \"../../core-backend\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\n\r\ninterface ITaskResult {\r\n stats: QueryStats;\r\n error?: any;\r\n}\r\n\r\ninterface IScenario {\r\n name: string;\r\n config?: DbQueryConfig;\r\n totalBatches: number;\r\n taskPerBatch: number;\r\n createReader: (db: ECDb | IModelDb) => ECSqlReader;\r\n}\r\n\r\nclass LoadSimulator {\r\n constructor(public db: ECDb | IModelDb, public scenario: IScenario) { }\r\n private async runQueryTask(reader: ECSqlReader): Promise<ITaskResult> {\r\n try {\r\n while (await reader.step()) { }\r\n return { stats: reader.stats };\r\n } catch (err) {\r\n return { stats: reader.stats, error: err };\r\n }\r\n }\r\n\r\n public async run() {\r\n ConcurrentQuery.shutdown(this.db[_nativeDb]);\r\n if (this.scenario.config) {\r\n const config = ConcurrentQuery.resetConfig(this.db[_nativeDb], this.scenario.config);\r\n // eslint-disable-next-line no-console\r\n console.log(config);\r\n }\r\n const overallTime = new StopWatch();\r\n overallTime.start();\r\n const results: ITaskResult[] = [];\r\n for (let i = 0; i < this.scenario.totalBatches; ++i) {\r\n const promises: Promise<ITaskResult>[] = [];\r\n const readerTasks = Array(this.scenario.taskPerBatch).fill(undefined).map(() => this.scenario.createReader(this.db));\r\n readerTasks.forEach((reader) => {\r\n promises.push(this.runQueryTask(reader));\r\n });\r\n results.push(... await Promise.all(promises));\r\n\r\n }\r\n overallTime.stop();\r\n const errors = results.filter((x) => x.error !== undefined);\r\n const errorsMap = new Map<string, number>();\r\n errors.forEach((x) => {\r\n if (x.error instanceof Error) {\r\n if (!errorsMap.has(x.error.message)) {\r\n errorsMap.set(x.error.message, 1);\r\n } else {\r\n errorsMap.set(x.error.message, errorsMap.get(x.error.message)! + 1);\r\n }\r\n } else {\r\n if (!errorsMap.has(\"error\")) {\r\n errorsMap.set(\"error\", 1);\r\n } else {\r\n errorsMap.set(\"error\", errorsMap.get(\"error\")! + 1);\r\n }\r\n }\r\n });\r\n const errorCount = errors.length;\r\n let backendCpuTime: bigint = BigInt(0);\r\n let backendTotalTime: bigint = BigInt(0);\r\n let backendMemUsed: bigint = BigInt(0);\r\n let backendRowsReturned: bigint = BigInt(0);\r\n let totalTime: bigint = BigInt(0);\r\n let retryCount: bigint = BigInt(0);\r\n let prepareTime: bigint = BigInt(0);\r\n\r\n // Calculate average\r\n results.forEach((r: ITaskResult) => {\r\n backendCpuTime += BigInt(r.stats.backendCpuTime);\r\n backendTotalTime += BigInt(r.stats.backendTotalTime);\r\n backendMemUsed += BigInt(r.stats.backendMemUsed);\r\n backendRowsReturned += BigInt(r.stats.backendRowsReturned);\r\n totalTime += BigInt(r.stats.totalTime);\r\n retryCount += BigInt(r.stats.retryCount);\r\n prepareTime += BigInt(r.stats.prepareTime);\r\n });\r\n\r\n backendCpuTime /= BigInt(results.length);\r\n backendTotalTime /= BigInt(results.length);\r\n backendMemUsed /= BigInt(results.length);\r\n backendRowsReturned /= BigInt(results.length);\r\n totalTime /= BigInt(results.length);\r\n retryCount /= BigInt(results.length);\r\n // prepareTime /= BigInt(results.length);\r\n\r\n return {\r\n result: {\r\n backendCpuTime,\r\n backendTotalTime,\r\n backendMemUsed,\r\n backendRowsReturned,\r\n totalTime,\r\n retryCount,\r\n prepareTime,\r\n },\r\n overallTimeInSec: overallTime.currentSeconds,\r\n errorCount,\r\n totalQueries: results.length,\r\n errorMap: errorsMap\r\n };\r\n\r\n }\r\n}\r\ndescribe.skip(\"ConcurrentQueryLoad\", () => {\r\n it(\"should run\", async () => {\r\n Logger.initializeToConsole();\r\n Logger.setLevel(\"ECDb.ConcurrentQuery\", LogLevel.Trace);\r\n\r\n const scenario: IScenario = {\r\n name: \"ConcurrentQueryLoad\",\r\n config: {\r\n globalQuota: { time: 1, memory: 8388608 },\r\n workerThreads: 1,\r\n },\r\n totalBatches: 1,\r\n taskPerBatch: 1,\r\n createReader: (dbs: ECDb | IModelDb) => {\r\n const queries = [\r\n {\r\n sql: `\r\n WITH sequence(n) AS (\r\n SELECT 1\r\n UNION ALL\r\n SELECT n + 1 FROM sequence WHERE n < 10000000\r\n )\r\n SELECT COUNT(*)\r\n FROM bis.SpatialIndex i, sequence s\r\n WHERE i.ECInstanceId MATCH iModel_spatial_overlap_aabb(\r\n iModel_bbox(random(), random(), random(), random(),random(), random()))`\r\n },\r\n {\r\n sql: `\r\n WITH sequence(n) AS (\r\n SELECT 1\r\n UNION ALL\r\n SELECT n + 1 FROM sequence WHERE n < 10000000\r\n )\r\n SELECT COUNT(*) FROM sequence`\r\n },\r\n {\r\n sql: \"SELECT $ FROM bis.Element LIMIT 10000\"\r\n }\r\n ];\r\n const idx = Math.floor(Math.random() * queries.length);\r\n return dbs.createQueryReader(queries[idx].sql);\r\n }\r\n };\r\n\r\n const verySmallFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(verySmallFile);\r\n const simulator = new LoadSimulator(db, scenario);\r\n const result = await simulator.run();\r\n // eslint-disable-next-line no-console\r\n console.log(result);\r\n db.close();\r\n expect(result.errorCount).to.be.equal(0);\r\n });\r\n});\r\n"]}
|
|
1
|
+
{"version":3,"file":"ConcurrentQueryLoad.test.js","sourceRoot":"","sources":["../../../../src/test/ecdb/ConcurrentQueryLoad.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger, LogLevel, StopWatch } from \"@itwin/core-bentley\";\r\nimport { DbQueryConfig, ECSqlReader, QueryStats } from \"@itwin/core-common\";\r\nimport { expect } from \"chai\";\r\nimport * as sinon from \"sinon\";\r\nimport { ConcurrentQuery } from \"../../ConcurrentQuery\";\r\nimport { ECDb } from \"../../ECDb\";\r\nimport { IModelDb, SnapshotDb } from \"../../IModelDb\";\r\nimport { _nativeDb } from \"../../core-backend\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\n\r\ninterface ITaskResult {\r\n stats: QueryStats;\r\n error?: any;\r\n}\r\n\r\ninterface IScenario {\r\n name: string;\r\n config?: DbQueryConfig;\r\n totalBatches: number;\r\n taskPerBatch: number;\r\n createReader: (db: ECDb | IModelDb) => ECSqlReader;\r\n}\r\n\r\nclass LoadSimulator {\r\n constructor(public db: ECDb | IModelDb, public scenario: IScenario) { }\r\n private async runQueryTask(reader: ECSqlReader): Promise<ITaskResult> {\r\n try {\r\n while (await reader.step()) { }\r\n return { stats: reader.stats };\r\n } catch (err) {\r\n return { stats: reader.stats, error: err };\r\n }\r\n }\r\n\r\n public async run() {\r\n ConcurrentQuery.shutdown(this.db[_nativeDb]);\r\n if (this.scenario.config) {\r\n const config = ConcurrentQuery.resetConfig(this.db[_nativeDb], this.scenario.config);\r\n // eslint-disable-next-line no-console\r\n console.log(config);\r\n }\r\n const overallTime = new StopWatch();\r\n overallTime.start();\r\n const results: ITaskResult[] = [];\r\n for (let i = 0; i < this.scenario.totalBatches; ++i) {\r\n const promises: Promise<ITaskResult>[] = [];\r\n const readerTasks = Array(this.scenario.taskPerBatch).fill(undefined).map(() => this.scenario.createReader(this.db));\r\n readerTasks.forEach((reader) => {\r\n promises.push(this.runQueryTask(reader));\r\n });\r\n results.push(... await Promise.all(promises));\r\n\r\n }\r\n overallTime.stop();\r\n const errors = results.filter((x) => x.error !== undefined);\r\n const errorsMap = new Map<string, number>();\r\n errors.forEach((x) => {\r\n if (x.error instanceof Error) {\r\n if (!errorsMap.has(x.error.message)) {\r\n errorsMap.set(x.error.message, 1);\r\n } else {\r\n errorsMap.set(x.error.message, errorsMap.get(x.error.message)! + 1);\r\n }\r\n } else {\r\n if (!errorsMap.has(\"error\")) {\r\n errorsMap.set(\"error\", 1);\r\n } else {\r\n errorsMap.set(\"error\", errorsMap.get(\"error\")! + 1);\r\n }\r\n }\r\n });\r\n const errorCount = errors.length;\r\n let backendCpuTime: bigint = BigInt(0);\r\n let backendTotalTime = 0;\r\n let backendMemUsed: bigint = BigInt(0);\r\n let backendRowsReturned: bigint = BigInt(0);\r\n let totalTime = 0;\r\n let retryCount: bigint = BigInt(0);\r\n let prepareTime = 0;\r\n\r\n // Calculate average\r\n results.forEach((r: ITaskResult) => {\r\n backendCpuTime += BigInt(r.stats.backendCpuTime);\r\n backendTotalTime += r.stats.backendTotalTime;\r\n backendMemUsed += BigInt(r.stats.backendMemUsed);\r\n backendRowsReturned += BigInt(r.stats.backendRowsReturned);\r\n totalTime += r.stats.totalTime;\r\n retryCount += BigInt(r.stats.retryCount);\r\n prepareTime += r.stats.prepareTime;\r\n });\r\n\r\n backendCpuTime /= BigInt(results.length);\r\n backendTotalTime /= results.length;\r\n backendMemUsed /= BigInt(results.length);\r\n backendRowsReturned /= BigInt(results.length);\r\n totalTime /= results.length;\r\n retryCount /= BigInt(results.length);\r\n // prepareTime /= results.length;\r\n\r\n return {\r\n result: {\r\n backendCpuTime,\r\n backendTotalTime,\r\n backendMemUsed,\r\n backendRowsReturned,\r\n totalTime,\r\n retryCount,\r\n prepareTime,\r\n },\r\n overallTimeInSec: overallTime.currentSeconds,\r\n errorCount,\r\n totalQueries: results.length,\r\n errorMap: errorsMap\r\n };\r\n\r\n }\r\n}\r\ndescribe(\"ConcurrentQueryLoad statistics\", () => {\r\n it(\"preserves fractional timing averages and preparation totals\", async () => {\r\n const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile(\"test.bim\"));\r\n const sandbox = sinon.createSandbox();\r\n try {\r\n let queryIndex = 0;\r\n const simulator = new LoadSimulator(db, {\r\n name: \"fractional timings\",\r\n totalBatches: 1,\r\n taskPerBatch: 2,\r\n createReader: () => {\r\n const reader = db.createQueryReader(\"SELECT 1\");\r\n const timing = ++queryIndex === 1 ? 0.25 : 0.5;\r\n sandbox.stub(reader, \"step\").resolves(false);\r\n sandbox.stub(reader, \"stats\").get((): QueryStats => ({\r\n backendCpuTime: 10,\r\n backendTotalTime: timing,\r\n backendMemUsed: 20,\r\n backendRowsReturned: 1,\r\n totalTime: timing * 2,\r\n retryCount: 0,\r\n prepareTime: timing,\r\n }));\r\n return reader;\r\n },\r\n });\r\n const result = await simulator.run();\r\n expect(result.errorCount).to.equal(0);\r\n expect(result.totalQueries).to.equal(2);\r\n expect(result.result.backendTotalTime).to.equal(0.375);\r\n expect(result.result.totalTime).to.equal(0.75);\r\n expect(result.result.prepareTime).to.equal(0.75);\r\n expect(result.result.backendCpuTime).to.equal(10n);\r\n expect(result.result.backendRowsReturned).to.equal(1n);\r\n } finally {\r\n sandbox.restore();\r\n db.close();\r\n }\r\n });\r\n});\r\ndescribe.skip(\"ConcurrentQueryLoad\", () => {\r\n it(\"should run\", async () => {\r\n Logger.initializeToConsole();\r\n Logger.setLevel(\"ECDb.ConcurrentQuery\", LogLevel.Trace);\r\n\r\n const scenario: IScenario = {\r\n name: \"ConcurrentQueryLoad\",\r\n config: {\r\n globalQuota: { time: 1, memory: 8388608 },\r\n workerThreads: 1,\r\n },\r\n totalBatches: 1,\r\n taskPerBatch: 1,\r\n createReader: (dbs: ECDb | IModelDb) => {\r\n const queries = [\r\n {\r\n sql: `\r\n WITH sequence(n) AS (\r\n SELECT 1\r\n UNION ALL\r\n SELECT n + 1 FROM sequence WHERE n < 10000000\r\n )\r\n SELECT COUNT(*)\r\n FROM bis.SpatialIndex i, sequence s\r\n WHERE i.ECInstanceId MATCH iModel_spatial_overlap_aabb(\r\n iModel_bbox(random(), random(), random(), random(),random(), random()))`\r\n },\r\n {\r\n sql: `\r\n WITH sequence(n) AS (\r\n SELECT 1\r\n UNION ALL\r\n SELECT n + 1 FROM sequence WHERE n < 10000000\r\n )\r\n SELECT COUNT(*) FROM sequence`\r\n },\r\n {\r\n sql: \"SELECT $ FROM bis.Element LIMIT 10000\"\r\n }\r\n ];\r\n const idx = Math.floor(Math.random() * queries.length);\r\n return dbs.createQueryReader(queries[idx].sql);\r\n }\r\n };\r\n\r\n const verySmallFile = IModelTestUtils.resolveAssetFile(\"test.bim\");\r\n const db = SnapshotDb.openFile(verySmallFile);\r\n const simulator = new LoadSimulator(db, scenario);\r\n const result = await simulator.run();\r\n // eslint-disable-next-line no-console\r\n console.log(result);\r\n db.close();\r\n expect(result.errorCount).to.be.equal(0);\r\n });\r\n});\r\n"]}
|
|
@@ -517,7 +517,8 @@ describe("ECSql Query", () => {
|
|
|
517
517
|
assert.equal(reader.stats.backendRowsReturned, 46);
|
|
518
518
|
assert.isTrue(reader.stats.backendCpuTime > 0);
|
|
519
519
|
assert.isTrue(reader.stats.backendMemUsed > 1000);
|
|
520
|
-
|
|
520
|
+
// Primary-connection requests complete synchronously and can finish within the same millisecond.
|
|
521
|
+
assert.isAtLeast(reader.stats.totalTime, 0);
|
|
521
522
|
});
|
|
522
523
|
it("concurrent query use idset", async () => {
|
|
523
524
|
const ids = [];
|