@itwin/core-backend 5.15.0-dev.7 → 5.15.0
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 +46 -1
- package/lib/cjs/BlobContainerService.d.ts +2 -0
- package/lib/cjs/BlobContainerService.d.ts.map +1 -1
- package/lib/cjs/BlobContainerService.js.map +1 -1
- package/lib/cjs/BriefcaseManager.d.ts +2 -1
- package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
- package/lib/cjs/BriefcaseManager.js +39 -9
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/ChangeUnifier.d.ts +82 -0
- package/lib/cjs/ChangeUnifier.d.ts.map +1 -0
- package/lib/cjs/ChangeUnifier.js +163 -0
- package/lib/cjs/ChangeUnifier.js.map +1 -0
- package/lib/cjs/ChangesetReader.d.ts +21 -2
- package/lib/cjs/ChangesetReader.d.ts.map +1 -1
- package/lib/cjs/ChangesetReader.js +37 -1
- package/lib/cjs/ChangesetReader.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts +15 -0
- package/lib/cjs/CloudSqlite.d.ts.map +1 -1
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/lib/cjs/ECDb.d.ts +1 -0
- package/lib/cjs/ECDb.d.ts.map +1 -1
- package/lib/cjs/ECDb.js +4 -1
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/EditTxn.d.ts +61 -19
- package/lib/cjs/EditTxn.d.ts.map +1 -1
- package/lib/cjs/EditTxn.js +84 -29
- package/lib/cjs/EditTxn.js.map +1 -1
- package/lib/cjs/GeoCoordConfig.d.ts +1 -0
- package/lib/cjs/GeoCoordConfig.d.ts.map +1 -1
- package/lib/cjs/GeoCoordConfig.js +12 -8
- package/lib/cjs/GeoCoordConfig.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +22 -9
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +54 -12
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/NativeHost.d.ts.map +1 -1
- package/lib/cjs/NativeHost.js +5 -1
- package/lib/cjs/NativeHost.js.map +1 -1
- package/lib/cjs/Relationship.d.ts +28 -0
- package/lib/cjs/Relationship.d.ts.map +1 -1
- package/lib/cjs/Relationship.js +78 -0
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/SchemaSync.d.ts.map +1 -1
- package/lib/cjs/SchemaSync.js +1 -0
- package/lib/cjs/SchemaSync.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts +126 -89
- package/lib/cjs/TxnManager.d.ts.map +1 -1
- package/lib/cjs/TxnManager.js +114 -76
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/ViewStateHydrator.d.ts.map +1 -1
- package/lib/cjs/ViewStateHydrator.js.map +1 -1
- package/lib/cjs/ViewStore.d.ts.map +1 -1
- package/lib/cjs/ViewStore.js +62 -19
- package/lib/cjs/ViewStore.js.map +1 -1
- package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
- package/lib/cjs/annotations/LeaderGeometry.js +3 -0
- package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
- package/lib/cjs/core-backend.d.ts +1 -0
- package/lib/cjs/core-backend.d.ts.map +1 -1
- package/lib/cjs/core-backend.js +1 -0
- package/lib/cjs/core-backend.js.map +1 -1
- package/lib/cjs/internal/BriefcaseUtils.d.ts +19 -0
- package/lib/cjs/internal/BriefcaseUtils.d.ts.map +1 -0
- package/lib/cjs/internal/BriefcaseUtils.js +65 -0
- package/lib/cjs/internal/BriefcaseUtils.js.map +1 -0
- package/lib/cjs/internal/QueryMetadataCache.d.ts +44 -0
- package/lib/cjs/internal/QueryMetadataCache.d.ts.map +1 -0
- package/lib/cjs/internal/QueryMetadataCache.js +107 -0
- package/lib/cjs/internal/QueryMetadataCache.js.map +1 -0
- package/lib/cjs/internal/Symbols.d.ts +9 -0
- package/lib/cjs/internal/Symbols.d.ts.map +1 -1
- package/lib/cjs/internal/Symbols.js +10 -1
- package/lib/cjs/internal/Symbols.js.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.js +20 -6
- package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
- package/lib/cjs/workspace/SettingsEditor.d.ts +4 -3
- package/lib/cjs/workspace/SettingsEditor.d.ts.map +1 -1
- package/lib/cjs/workspace/SettingsEditor.js +7 -5
- package/lib/cjs/workspace/SettingsEditor.js.map +1 -1
- package/lib/esm/BlobContainerService.d.ts +2 -0
- package/lib/esm/BlobContainerService.d.ts.map +1 -1
- package/lib/esm/BlobContainerService.js.map +1 -1
- package/lib/esm/BriefcaseManager.d.ts +2 -1
- package/lib/esm/BriefcaseManager.d.ts.map +1 -1
- package/lib/esm/BriefcaseManager.js +40 -10
- package/lib/esm/BriefcaseManager.js.map +1 -1
- package/lib/esm/ChangeUnifier.d.ts +82 -0
- package/lib/esm/ChangeUnifier.d.ts.map +1 -0
- package/lib/esm/ChangeUnifier.js +159 -0
- package/lib/esm/ChangeUnifier.js.map +1 -0
- package/lib/esm/ChangesetReader.d.ts +21 -2
- package/lib/esm/ChangesetReader.d.ts.map +1 -1
- package/lib/esm/ChangesetReader.js +38 -2
- package/lib/esm/ChangesetReader.js.map +1 -1
- package/lib/esm/CloudSqlite.d.ts +15 -0
- package/lib/esm/CloudSqlite.d.ts.map +1 -1
- package/lib/esm/CloudSqlite.js.map +1 -1
- package/lib/esm/ECDb.d.ts +1 -0
- package/lib/esm/ECDb.d.ts.map +1 -1
- package/lib/esm/ECDb.js +4 -1
- package/lib/esm/ECDb.js.map +1 -1
- package/lib/esm/EditTxn.d.ts +61 -19
- package/lib/esm/EditTxn.d.ts.map +1 -1
- package/lib/esm/EditTxn.js +85 -30
- package/lib/esm/EditTxn.js.map +1 -1
- package/lib/esm/GeoCoordConfig.d.ts +1 -0
- package/lib/esm/GeoCoordConfig.d.ts.map +1 -1
- package/lib/esm/GeoCoordConfig.js +12 -8
- package/lib/esm/GeoCoordConfig.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +22 -9
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +56 -14
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/NativeHost.d.ts.map +1 -1
- package/lib/esm/NativeHost.js +5 -1
- package/lib/esm/NativeHost.js.map +1 -1
- package/lib/esm/Relationship.d.ts +28 -0
- package/lib/esm/Relationship.d.ts.map +1 -1
- package/lib/esm/Relationship.js +78 -0
- package/lib/esm/Relationship.js.map +1 -1
- package/lib/esm/SchemaSync.d.ts.map +1 -1
- package/lib/esm/SchemaSync.js +1 -0
- package/lib/esm/SchemaSync.js.map +1 -1
- package/lib/esm/TxnManager.d.ts +126 -89
- package/lib/esm/TxnManager.d.ts.map +1 -1
- package/lib/esm/TxnManager.js +116 -78
- package/lib/esm/TxnManager.js.map +1 -1
- package/lib/esm/ViewStateHydrator.d.ts.map +1 -1
- package/lib/esm/ViewStateHydrator.js.map +1 -1
- package/lib/esm/ViewStore.d.ts.map +1 -1
- package/lib/esm/ViewStore.js +62 -19
- package/lib/esm/ViewStore.js.map +1 -1
- package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
- package/lib/esm/annotations/LeaderGeometry.js +3 -0
- package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
- package/lib/esm/core-backend.d.ts +1 -0
- package/lib/esm/core-backend.d.ts.map +1 -1
- package/lib/esm/core-backend.js +1 -0
- package/lib/esm/core-backend.js.map +1 -1
- package/lib/esm/internal/BriefcaseUtils.d.ts +19 -0
- package/lib/esm/internal/BriefcaseUtils.d.ts.map +1 -0
- package/lib/esm/internal/BriefcaseUtils.js +61 -0
- package/lib/esm/internal/BriefcaseUtils.js.map +1 -0
- package/lib/esm/internal/QueryMetadataCache.d.ts +44 -0
- package/lib/esm/internal/QueryMetadataCache.d.ts.map +1 -0
- package/lib/esm/internal/QueryMetadataCache.js +103 -0
- package/lib/esm/internal/QueryMetadataCache.js.map +1 -0
- package/lib/esm/internal/Symbols.d.ts +9 -0
- package/lib/esm/internal/Symbols.d.ts.map +1 -1
- package/lib/esm/internal/Symbols.js +9 -0
- package/lib/esm/internal/Symbols.js.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.js +20 -6
- package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
- package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
- package/lib/esm/rpc-impl/IModelReadRpcImpl.js.map +1 -1
- package/lib/esm/test/annotations/LeaderGeometry.test.js +15 -1
- package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
- package/lib/esm/test/ecdb/ConcurrentQuery.test.js +144 -30
- package/lib/esm/test/ecdb/ConcurrentQuery.test.js.map +1 -1
- package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts +2 -0
- package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts.map +1 -0
- package/lib/esm/test/ecdb/QueryMetadataCache.test.js +630 -0
- package/lib/esm/test/ecdb/QueryMetadataCache.test.js.map +1 -0
- package/lib/esm/test/element/DeleteDefinitionElements.test.js +403 -249
- package/lib/esm/test/element/DeleteDefinitionElements.test.js.map +1 -1
- package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts +2 -0
- package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts.map +1 -0
- package/lib/esm/test/element/RelationshipBatchLookup.test.js +202 -0
- package/lib/esm/test/element/RelationshipBatchLookup.test.js.map +1 -0
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js +187 -1
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts +2 -0
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts.map +1 -0
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js +142 -0
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelGeolocation.test.js +8 -6
- package/lib/esm/test/imodel/IModelGeolocation.test.js.map +1 -1
- package/lib/esm/test/imodel/IModelProps.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelProps.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelProps.test.js +411 -0
- package/lib/esm/test/imodel/IModelProps.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts +2 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts.map +1 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js +240 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewValidation.test.js +2 -8
- package/lib/esm/test/schema/SchemaViewValidation.test.js.map +1 -1
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts +2 -0
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js +159 -0
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js.map +1 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.d.ts +2 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.js +732 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.js.map +1 -0
- package/lib/esm/test/standalone/DeleteElements.test.js +962 -83
- package/lib/esm/test/standalone/DeleteElements.test.js.map +1 -1
- package/lib/esm/test/standalone/EditTxn.test.js +72 -1
- package/lib/esm/test/standalone/EditTxn.test.js.map +1 -1
- package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts +2 -0
- package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/GeoCoordConfig.test.js +158 -0
- package/lib/esm/test/standalone/GeoCoordConfig.test.js.map +1 -0
- package/lib/esm/test/standalone/ViewStoreDb.test.js +53 -0
- package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
- package/lib/esm/test/workspace/SettingsContainers.test.d.ts +2 -0
- package/lib/esm/test/workspace/SettingsContainers.test.d.ts.map +1 -0
- package/lib/esm/test/workspace/SettingsContainers.test.js +95 -0
- package/lib/esm/test/workspace/SettingsContainers.test.js.map +1 -0
- package/lib/esm/workspace/SettingsEditor.d.ts +4 -3
- package/lib/esm/workspace/SettingsEditor.d.ts.map +1 -1
- package/lib/esm/workspace/SettingsEditor.js +7 -5
- package/lib/esm/workspace/SettingsEditor.js.map +1 -1
- package/package.json +18 -18
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DbResponseStatus } from "@itwin/core-common";
|
|
1
|
+
import { DbResponseStatus, DbValueFormat, QueryBinder } from "@itwin/core-common";
|
|
2
2
|
import { expect } from "chai";
|
|
3
3
|
import * as os from "os";
|
|
4
4
|
import { ConcurrentQuery } from "../../ConcurrentQuery";
|
|
@@ -33,6 +33,9 @@ describe("ConcurrentQuery", () => {
|
|
|
33
33
|
progressOpCount: 5000,
|
|
34
34
|
requestQueueSize: 2000,
|
|
35
35
|
statementCacheSizePerWorker: 40,
|
|
36
|
+
enableCursors: true,
|
|
37
|
+
maxCursorsPerWorker: -1,
|
|
38
|
+
cursorIdleTimeout: 30,
|
|
36
39
|
workerThreads: defaultWorkerThreads(),
|
|
37
40
|
};
|
|
38
41
|
const config = ConcurrentQuery.resetConfig(db[_nativeDb], {});
|
|
@@ -53,6 +56,9 @@ describe("ConcurrentQuery", () => {
|
|
|
53
56
|
progressOpCount: 6000,
|
|
54
57
|
requestQueueSize: 1000,
|
|
55
58
|
statementCacheSizePerWorker: 20,
|
|
59
|
+
enableCursors: false,
|
|
60
|
+
maxCursorsPerWorker: 3,
|
|
61
|
+
cursorIdleTimeout: 10,
|
|
56
62
|
workerThreads: 1,
|
|
57
63
|
};
|
|
58
64
|
const config = ConcurrentQuery.resetConfig(db[_nativeDb], modifiedConfig);
|
|
@@ -67,6 +73,94 @@ describe("ConcurrentQuery", () => {
|
|
|
67
73
|
expect(config.workerThreads).eq(defaultWorkerThreads());
|
|
68
74
|
db.close();
|
|
69
75
|
});
|
|
76
|
+
it("round-trips the page-cache target in KiB and rejects invalid sizes", () => {
|
|
77
|
+
const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim"));
|
|
78
|
+
try {
|
|
79
|
+
expect(ConcurrentQuery.resetConfig(db[_nativeDb], {}).cacheSizeInKB).eq(undefined);
|
|
80
|
+
for (const cacheSizeInKB of [0, 8192, 2147483647])
|
|
81
|
+
expect(ConcurrentQuery.resetConfig(db[_nativeDb], { cacheSizeInKB }).cacheSizeInKB).eq(cacheSizeInKB);
|
|
82
|
+
for (const cacheSizeInKB of [-1, 1.5, 2147483648, NaN, Infinity, -Infinity])
|
|
83
|
+
expect(ConcurrentQuery.resetConfig(db[_nativeDb], { cacheSizeInKB }).cacheSizeInKB).eq(undefined);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
db.close();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
it("resumes finite pages without losing rows, with OFFSET fallback when disabled", async () => {
|
|
90
|
+
const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim"));
|
|
91
|
+
try {
|
|
92
|
+
for (const enableCursors of [false, true]) {
|
|
93
|
+
ConcurrentQuery.shutdown(db[_nativeDb]);
|
|
94
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: 1, enableCursors, globalQuota: { time: 60, memory: 1 } });
|
|
95
|
+
const rows = [];
|
|
96
|
+
let resumed = 0;
|
|
97
|
+
while (rows.length < 20) {
|
|
98
|
+
const resp = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], {
|
|
99
|
+
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",
|
|
100
|
+
cursorId: "finite-reader",
|
|
101
|
+
limit: { offset: 5 + rows.length, count: 20 - rows.length },
|
|
102
|
+
});
|
|
103
|
+
expect(resp.status).eq(DbResponseStatus.Partial);
|
|
104
|
+
expect(resp.data).deep.eq([[45 - rows.length]]);
|
|
105
|
+
rows.push(resp.data[0][0]);
|
|
106
|
+
if (resp.stats.resumed)
|
|
107
|
+
++resumed;
|
|
108
|
+
}
|
|
109
|
+
expect(rows).deep.eq(Array.from({ length: 20 }, (_, i) => 45 - i));
|
|
110
|
+
expect(resumed).eq(enableCursors ? 19 : 0);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
db.close();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
it("isolates readers and bindings and falls back after cursor eviction", async () => {
|
|
118
|
+
const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim"));
|
|
119
|
+
try {
|
|
120
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: 1, maxCursorsPerWorker: 1, globalQuota: { time: 60, memory: 1 } });
|
|
121
|
+
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";
|
|
122
|
+
const page = async (cursorId, offset, value) => ConcurrentQuery.executeQueryRequest(db[_nativeDb], {
|
|
123
|
+
query, cursorId, args: new QueryBinder().bindInt(1, value).serialize(), limit: { offset, count: -1 },
|
|
124
|
+
});
|
|
125
|
+
expect((await page("a", 0, 0)).data).deep.eq([[1]]);
|
|
126
|
+
expect((await page("a", 1, 0)).stats.resumed).eq(true);
|
|
127
|
+
expect((await page("b", 0, 100)).data).deep.eq([[101]]);
|
|
128
|
+
const evicted = await page("a", 2, 0);
|
|
129
|
+
expect(evicted.stats.resumed).eq(false);
|
|
130
|
+
expect(evicted.data).deep.eq([[3]]);
|
|
131
|
+
const rebound = await page("a", 3, 100);
|
|
132
|
+
expect(rebound.stats.resumed).eq(false);
|
|
133
|
+
expect(rebound.data).deep.eq([[104]]);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
db.close();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
it("preserves class and navigation rendering across worker connections", async () => {
|
|
140
|
+
const db = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim"));
|
|
141
|
+
try {
|
|
142
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { workerThreads: defaultWorkerThreads(), globalQuota: { time: 60, memory: 8388608 } });
|
|
143
|
+
const query = "SELECT ECClassId, Schema FROM meta.ECClassDef ORDER BY ECInstanceId LIMIT 20";
|
|
144
|
+
for (const valueFormat of [DbValueFormat.ECSqlNames, DbValueFormat.JsNames]) {
|
|
145
|
+
const request = {
|
|
146
|
+
query, valueFormat,
|
|
147
|
+
convertClassIdsToClassNames: true,
|
|
148
|
+
};
|
|
149
|
+
const primary = await ConcurrentQuery.executeQueryRequest(db[_nativeDb], { ...request, usePrimaryConn: true });
|
|
150
|
+
expect(primary.status).eq(DbResponseStatus.Done);
|
|
151
|
+
expect(primary.data.length).eq(20);
|
|
152
|
+
const workers = await Promise.all(Array.from({ length: defaultWorkerThreads() * 2 }, async () => ConcurrentQuery.executeQueryRequest(db[_nativeDb], request)));
|
|
153
|
+
for (const worker of workers) {
|
|
154
|
+
expect(worker.status).eq(DbResponseStatus.Done);
|
|
155
|
+
expect(worker.data).deep.eq(primary.data);
|
|
156
|
+
expect(worker.meta).deep.eq(primary.meta);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
db.close();
|
|
162
|
+
}
|
|
163
|
+
});
|
|
70
164
|
it("time limit check", async () => {
|
|
71
165
|
const testFile = IModelTestUtils.resolveAssetFile("test.bim");
|
|
72
166
|
const db = SnapshotDb.openFile(testFile);
|
|
@@ -147,38 +241,46 @@ describe("ConcurrentQuery", () => {
|
|
|
147
241
|
it("queue limit check", async () => {
|
|
148
242
|
const testFile = IModelTestUtils.resolveAssetFile("test.bim");
|
|
149
243
|
const db = SnapshotDb.openFile(testFile);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
244
|
+
try {
|
|
245
|
+
const requestQueueSize = 40;
|
|
246
|
+
const requestCount = 60;
|
|
247
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { requestQueueSize, ignoreDelay: false, globalQuota: { time: 5, memory: 100000 } });
|
|
248
|
+
// A delay keeps accepted requests in the queue (workers only dequeue requests whose delay has elapsed),
|
|
249
|
+
// so the queue fills up deterministically regardless of how fast the worker threads are.
|
|
250
|
+
const req = { query: "SELECT 1", delay: 2000 };
|
|
251
|
+
const responsePromises = [];
|
|
252
|
+
for (let i = 0; i < requestCount; ++i) {
|
|
253
|
+
responsePromises.push(ConcurrentQuery.executeQueryRequest(db[_nativeDb], req));
|
|
254
|
+
}
|
|
255
|
+
const responses = await Promise.all(responsePromises);
|
|
256
|
+
const queueFullResponses = responses.filter((x) => x.status === DbResponseStatus.QueueFull);
|
|
257
|
+
expect(queueFullResponses.length).to.equal(requestCount - requestQueueSize);
|
|
258
|
+
const otherStatuses = responses.filter((x) => x.status !== DbResponseStatus.QueueFull).map((x) => x.status);
|
|
259
|
+
expect(otherStatuses).to.have.lengthOf(requestQueueSize);
|
|
260
|
+
expect(otherStatuses.every((x) => x === DbResponseStatus.Done)).to.be.true;
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
db.close();
|
|
159
264
|
}
|
|
160
|
-
const responses = await Promise.all(responsePromises);
|
|
161
|
-
const queueResponses = Array.from(responses.filter((x) => x.status === DbResponseStatus.QueueFull));
|
|
162
|
-
expect(queueResponses.length).to.be.greaterThanOrEqual(10);
|
|
163
|
-
db.close();
|
|
164
265
|
});
|
|
165
266
|
it("timeout check", async () => {
|
|
166
267
|
const testFile = IModelTestUtils.resolveAssetFile("test.bim");
|
|
167
268
|
const db = SnapshotDb.openFile(testFile);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
269
|
+
try {
|
|
270
|
+
ConcurrentQuery.resetConfig(db[_nativeDb], { ignoreDelay: false, monitorPollInterval: 1000, globalQuota: { time: 1, memory: 1000 } });
|
|
271
|
+
// Keep requests queued past their deadline without generating large result sets.
|
|
272
|
+
const req = { query: "SELECT 1", delay: 2000 };
|
|
273
|
+
const responsePromises = [];
|
|
274
|
+
for (let i = 0; i < 100; ++i) {
|
|
275
|
+
responsePromises.push(ConcurrentQuery.executeQueryRequest(db[_nativeDb], req));
|
|
276
|
+
}
|
|
277
|
+
const responses = await Promise.all(responsePromises);
|
|
278
|
+
for (const response of responses)
|
|
279
|
+
expect(response.status).equals(DbResponseStatus.Timeout);
|
|
280
|
+
}
|
|
281
|
+
finally {
|
|
282
|
+
db.close();
|
|
177
283
|
}
|
|
178
|
-
const responses = await Promise.all(responsePromises);
|
|
179
|
-
const queueResponses = Array.from(responses.filter((x) => x.status === DbResponseStatus.Timeout));
|
|
180
|
-
expect(queueResponses.length).to.be.greaterThanOrEqual(10);
|
|
181
|
-
db.close();
|
|
182
284
|
});
|
|
183
285
|
it("should handle concurrent queries during shutdown without deadlock", async () => {
|
|
184
286
|
const testFile = IModelTestUtils.resolveAssetFile("test.bim");
|
|
@@ -187,9 +289,18 @@ describe("ConcurrentQuery", () => {
|
|
|
187
289
|
const config = {
|
|
188
290
|
requestQueueSize: 1000,
|
|
189
291
|
statementCacheSizePerWorker: 1, // Force frequent prepare calls
|
|
292
|
+
ignoreDelay: false, // Honor request delays so some requests are guaranteed to still be queued at shutdown
|
|
190
293
|
};
|
|
191
294
|
// Reset configuration
|
|
192
295
|
ConcurrentQuery.resetConfig(iModelDb[_nativeDb], config);
|
|
296
|
+
// Requests that are still queued when shutdown happens are rejected with ShuttingDown. A delay keeps these
|
|
297
|
+
// requests from being dequeued by a worker, so they are deterministically queued at shutdown regardless of
|
|
298
|
+
// how fast or slow the worker threads are. They are enqueued first so they cannot be rejected with QueueFull.
|
|
299
|
+
const queuedRequestCount = 10;
|
|
300
|
+
const queuedPromises = [];
|
|
301
|
+
for (let i = 0; i < queuedRequestCount; ++i) {
|
|
302
|
+
queuedPromises.push(ConcurrentQuery.executeQueryRequest(iModelDb[_nativeDb], { query: "SELECT 1", delay: 5000 }));
|
|
303
|
+
}
|
|
193
304
|
const responsePromises = [];
|
|
194
305
|
const spamPromises = [];
|
|
195
306
|
let shouldStop = false;
|
|
@@ -213,11 +324,14 @@ describe("ConcurrentQuery", () => {
|
|
|
213
324
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
214
325
|
ConcurrentQuery.shutdown(iModelDb[_nativeDb]);
|
|
215
326
|
shouldStop = true;
|
|
216
|
-
// Wait for all promises to complete
|
|
327
|
+
// Wait for all promises to complete. If shutdown deadlocked, these would never settle and the test would time out.
|
|
328
|
+
const queuedResults = await Promise.allSettled(queuedPromises);
|
|
217
329
|
const results = await Promise.allSettled(responsePromises);
|
|
218
330
|
await Promise.allSettled(spamPromises);
|
|
219
|
-
|
|
220
|
-
|
|
331
|
+
expect(results.every((result) => result.status === "fulfilled")).to.be.true;
|
|
332
|
+
// Every request that was still queued at shutdown must be rejected with ShuttingDown.
|
|
333
|
+
const queuedStatuses = queuedResults.map((result) => result.status === "fulfilled" ? result.value.status : undefined);
|
|
334
|
+
expect(queuedStatuses).to.deep.equal(new Array(queuedRequestCount).fill(DbResponseStatus.ShuttingDown));
|
|
221
335
|
// Restore original config by resetting to default
|
|
222
336
|
ConcurrentQuery.resetConfig(iModelDb[_nativeDb], {});
|
|
223
337
|
iModelDb.close();
|
|
@@ -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 } 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 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 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(\"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 ConcurrentQuery.resetConfig(db[_nativeDb], { requestQueueSize: 40, globalQuota: { time: 5, memory: 100000 } });\r\n const req: 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 };\r\n\r\n const responsePromises: Promise<DbQueryResponse>[] = [];\r\n for (let i = 0; i < 60; ++i) {\r\n responsePromises.push(ConcurrentQuery.executeQueryRequest(db[_nativeDb], req));\r\n }\r\n const responses = await Promise.all(responsePromises);\r\n const queueResponses = Array.from(responses.filter((x) => x.status === DbResponseStatus.QueueFull));\r\n expect(queueResponses.length).to.be.greaterThanOrEqual(10);\r\n db.close();\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 ConcurrentQuery.resetConfig(db[_nativeDb], { monitorPollInterval: 1, globalQuota: { time: 5, memory: 10000000 } });\r\n const req: 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 };\r\n\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 const queueResponses = Array.from(responses.filter((x) => x.status === DbResponseStatus.Timeout));\r\n expect(queueResponses.length).to.be.greaterThanOrEqual(10);\r\n db.close();\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 };\r\n\r\n // Reset configuration\r\n ConcurrentQuery.resetConfig(iModelDb[_nativeDb], config);\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\r\n const results = await Promise.allSettled(responsePromises);\r\n await Promise.allSettled(spamPromises);\r\n\r\n const satisfiesShutDownResponse = results.some((result) => result.status === \"fulfilled\" && result.value.status === DbResponseStatus.ShuttingDown);\r\n\r\n expect(satisfiesShutDownResponse).to.be.true; // some queries should face shutdown\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(\"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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryMetadataCache.test.d.ts","sourceRoot":"","sources":["../../../../src/test/ecdb/QueryMetadataCache.test.ts"],"names":[],"mappings":""}
|