@lossless.org/client 1.17.0 → 1.18.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/nosqldb/classes.collection.d.ts +17 -0
- package/dist_ts/nosqldb/classes.collection.js +56 -4
- package/dist_ts/nosqldb/classes.collectiontopology.d.ts +9 -0
- package/dist_ts/nosqldb/classes.collectiontopology.js +33 -5
- package/dist_ts/nosqldb/classes.distributedcoordinator.js +7 -7
- package/dist_ts/nosqldb/classes.easystore.js +2 -2
- package/dist_ts/nosqldb/classes.ordinarypersistence.d.ts +5 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.js +7 -1
- package/dist_ts/nosqldb/classes.watcher.js +2 -2
- package/dist_ts/nosqldb/plugins.d.ts +1 -2
- package/dist_ts/nosqldb/plugins.js +2 -3
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.js +2 -2
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.js +2 -2
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.d.ts +1 -2
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.js +2 -3
- package/package.json +5 -6
- package/readme.md +1 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/nosqldb/classes.collection.ts +71 -0
- package/ts/nosqldb/classes.collectiontopology.ts +36 -9
- package/ts/nosqldb/classes.distributedcoordinator.ts +7 -7
- package/ts/nosqldb/classes.easystore.ts +1 -1
- package/ts/nosqldb/classes.ordinarypersistence.ts +8 -0
- package/ts/nosqldb/classes.watcher.ts +1 -1
- package/ts/nosqldb/plugins.ts +0 -2
- package/ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.ts +1 -1
- package/ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.ts +1 -1
- package/ts/sqldb/clickhouse/smartclickhouse.plugins.ts +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lossless.org/client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "One typed client for NoSQLDB, MongoDB, SQLDB, MariaDB, ClickHouse and S3 object storage.",
|
|
6
6
|
"exports": {
|
|
@@ -46,12 +46,11 @@
|
|
|
46
46
|
"homepage": "https://code.foss.global/lossless.org/client#readme",
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@push.rocks/lik": "^6.4.0",
|
|
49
|
-
"@push.rocks/smartdelay": "^3.0.5",
|
|
50
49
|
"@push.rocks/smartlog": "^3.2.1 || ^4.0.0",
|
|
51
50
|
"@push.rocks/smartmime": "^2.0.4",
|
|
52
51
|
"@push.rocks/smartobject": "^1.0.12",
|
|
53
52
|
"@push.rocks/smartpath": "^6.0.0",
|
|
54
|
-
"@push.rocks/smartpromise": "^4.
|
|
53
|
+
"@push.rocks/smartpromise": "^4.3.0",
|
|
55
54
|
"@push.rocks/smartrx": "^3.0.10",
|
|
56
55
|
"@push.rocks/smartstream": "^3.4.0",
|
|
57
56
|
"@push.rocks/smartstring": "^4.1.0",
|
|
@@ -81,10 +80,10 @@
|
|
|
81
80
|
"devDependencies": {
|
|
82
81
|
"@aws-sdk/client-s3": "^3.1039.0",
|
|
83
82
|
"@clickhouse/client": "1.23.1",
|
|
84
|
-
"@git.zone/tsbuild": "5.
|
|
85
|
-
"@git.zone/tsbundle": "3.1.
|
|
83
|
+
"@git.zone/tsbuild": "5.1.2",
|
|
84
|
+
"@git.zone/tsbundle": "3.1.2",
|
|
86
85
|
"@git.zone/tsrun": "3.0.2",
|
|
87
|
-
"@git.zone/tstest": "6.3.
|
|
86
|
+
"@git.zone/tstest": "6.3.4",
|
|
88
87
|
"@lossless.org/nosqldb": "8.0.2",
|
|
89
88
|
"@lossless.org/nosqldb-qualified": "npm:@lossless.org/nosqldb@10.7.2",
|
|
90
89
|
"@lossless.org/objectstorage": "10.3.1",
|
package/readme.md
CHANGED
|
@@ -114,6 +114,7 @@ Family imports preserve the established SmartData and SmartBucket names and cons
|
|
|
114
114
|
| Grouped totals element filter | `elementFilter: { 'lines.accountNumber': '1200' }` beside `unwind: 'lines'` counts and sums only the matching elements — one account's balance per side — with the atomic-filter operators on the unwound array and its declared element paths; any other path or operator is refused with `invalid_argument` |
|
|
115
115
|
| Grouped totals paging | rows come ordered by group key; `getGroupedTotalsPage()` returns `nextCursor` while `hasMore`, `cursor` continues after it, and `iterateGroupedTotals()` reads every group page by page — exact across pages for null, number, string and boolean group values (proven on NoSQLDB 8.0.2, 10.7.2 and MongoDB; ObjectId and date values are ordered by BSON type order but not yet covered by the paging tests), refused with `unsupported_operation` for other values, and a cursor from another query is refused with `invalid_argument` |
|
|
116
116
|
| Query-plan inspection | `Model.inspectQueryPlan(db, { filter, sort?, projection?, limit?, timeoutMS?, signal? })` — the winning plan's stages (`stage`, `depth`, `indexName`, `direction`) and `nReturned`/`totalKeysExamined`/`totalDocsExamined`, read-only and bounded, so a consumer proves a model query uses its intended index without raw driver access |
|
|
117
|
+
| Per-instance model binding | `bindDocToManager(manager, Model)` returns a subclass of a model declared with `@managed()` and no manager argument, named like the model and bound to that manager, so several databases use the same models at once; any other binding is refused with `invalid_configuration` |
|
|
117
118
|
| Disposable test databases on a unix socket | `SmartdataTestDatabase.create({ connection: { socketPath } })` from `@lossless.org/client/testsupport` reaches an engine that listens only on a unix-domain socket, fault helpers included; the loopback `host`/`port` form is unchanged |
|
|
118
119
|
|
|
119
120
|
`docs/source/smartdata/readme.md` documents each one with its refusals.
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
import {
|
|
38
38
|
collectionModelSchemaResolverSymbol,
|
|
39
39
|
collectionTopologyDbInspectionSymbol,
|
|
40
|
+
findCollectionModelSchemaResolver,
|
|
40
41
|
getExpectedCollectionTopologyForSchema,
|
|
41
42
|
getIdentityIndexName,
|
|
42
43
|
isIdentityIndexFor,
|
|
@@ -1219,12 +1220,23 @@ export const getIdentityDocumentIdField = (modelArg: any): string | undefined =>
|
|
|
1219
1220
|
: undefined;
|
|
1220
1221
|
};
|
|
1221
1222
|
|
|
1223
|
+
/**
|
|
1224
|
+
* Records on every collection binding whether its database follows the
|
|
1225
|
+
* receiver's manager. Only such a binding can be bound per instance through
|
|
1226
|
+
* `bindDocToManager()`; a binding with a fixed database or manager would
|
|
1227
|
+
* silently keep using it.
|
|
1228
|
+
*/
|
|
1229
|
+
const managerFollowsReceiverSymbol = Symbol(
|
|
1230
|
+
'@lossless.org/client.nosqldb.managerFollowsReceiver',
|
|
1231
|
+
);
|
|
1232
|
+
|
|
1222
1233
|
const installCollectionBinding = <
|
|
1223
1234
|
TModel extends SmartDataDbDoc<any, any>,
|
|
1224
1235
|
>(
|
|
1225
1236
|
constructorArg: TCollectionModelConstructor<TModel>,
|
|
1226
1237
|
dbResolverArg: (receiverArg?: unknown) => SmartdataDb,
|
|
1227
1238
|
schemaResolverArg: () => INormalizedCollectionModelSchema,
|
|
1239
|
+
managerFollowsReceiverArg = false,
|
|
1228
1240
|
): TCollectionModelConstructor<TModel> => {
|
|
1229
1241
|
const getCollection = (receiverArg?: unknown) => {
|
|
1230
1242
|
const db = dbResolverArg(receiverArg);
|
|
@@ -1251,6 +1263,12 @@ const installCollectionBinding = <
|
|
|
1251
1263
|
configurable: true,
|
|
1252
1264
|
writable: false,
|
|
1253
1265
|
});
|
|
1266
|
+
Object.defineProperty(constructorArg, managerFollowsReceiverSymbol, {
|
|
1267
|
+
value: managerFollowsReceiverArg,
|
|
1268
|
+
enumerable: false,
|
|
1269
|
+
configurable: true,
|
|
1270
|
+
writable: false,
|
|
1271
|
+
});
|
|
1254
1272
|
(constructorArg as any).className = constructorArg.name;
|
|
1255
1273
|
Object.defineProperty(constructorArg, 'collection', {
|
|
1256
1274
|
get(this: unknown) {
|
|
@@ -1620,6 +1638,58 @@ export const setDefaultManagerForDoc = <T,>(managerArg: IManager, dbDocArg: T):
|
|
|
1620
1638
|
return dbDocArg;
|
|
1621
1639
|
};
|
|
1622
1640
|
|
|
1641
|
+
/**
|
|
1642
|
+
* Returns a subclass of a `@managed()` model that is bound to `managerArg`.
|
|
1643
|
+
*
|
|
1644
|
+
* `setDefaultManagerForDoc()` sets the manager on the model itself, so every
|
|
1645
|
+
* binding of one model shares the manager set last. The bound subclass carries
|
|
1646
|
+
* its own manager instead: an application instance binds every model it uses,
|
|
1647
|
+
* and several instances run on several databases at once. The subclass keeps
|
|
1648
|
+
* the model's name, collection and declarations, and its statics and instances
|
|
1649
|
+
* use the manager's `db` whenever they reach the database, so the manager may
|
|
1650
|
+
* connect after binding. The binding is fixed for the subclass's lifetime.
|
|
1651
|
+
*
|
|
1652
|
+
* The model must be declared with `@managed()` without a manager argument;
|
|
1653
|
+
* any other binding would ignore the bound manager, and a subclass that
|
|
1654
|
+
* declares fields or a policy without a declaration of its own has no schema.
|
|
1655
|
+
* Both are refused with `invalid_configuration`.
|
|
1656
|
+
*/
|
|
1657
|
+
export const bindDocToManager = <
|
|
1658
|
+
TDoc extends abstract new (...args: never[]) => object,
|
|
1659
|
+
>(
|
|
1660
|
+
managerArg: IManager,
|
|
1661
|
+
docArg: TDoc,
|
|
1662
|
+
): TDoc => {
|
|
1663
|
+
if (
|
|
1664
|
+
typeof docArg !== 'function' ||
|
|
1665
|
+
!(docArg.prototype instanceof SmartDataDbDoc) ||
|
|
1666
|
+
(docArg as unknown as Record<symbol, unknown>)[managerFollowsReceiverSymbol] !== true ||
|
|
1667
|
+
findCollectionModelSchemaResolver(docArg) === undefined
|
|
1668
|
+
) {
|
|
1669
|
+
throw new SmartdataPersistenceError(
|
|
1670
|
+
'invalid_configuration',
|
|
1671
|
+
`Model "${typeof docArg === 'function' ? docArg.name : 'unknown'}" cannot be bound to a manager; ` +
|
|
1672
|
+
'declare it with @managed() without a manager argument.',
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
if (typeof managerArg !== 'object' || managerArg === null) {
|
|
1676
|
+
throw new SmartdataPersistenceError(
|
|
1677
|
+
'invalid_configuration',
|
|
1678
|
+
`Model "${docArg.name}" can only be bound to a manager object.`,
|
|
1679
|
+
);
|
|
1680
|
+
}
|
|
1681
|
+
const modelConstructor = docArg as unknown as new () => SmartDataDbDoc<object, object>;
|
|
1682
|
+
const boundDoc = class extends modelConstructor {};
|
|
1683
|
+
Object.defineProperty(boundDoc, 'name', { value: docArg.name, configurable: true });
|
|
1684
|
+
Object.defineProperty(boundDoc.prototype, 'defaultManager', {
|
|
1685
|
+
value: managerArg,
|
|
1686
|
+
enumerable: false,
|
|
1687
|
+
configurable: false,
|
|
1688
|
+
writable: false,
|
|
1689
|
+
});
|
|
1690
|
+
return boundDoc as unknown as TDoc;
|
|
1691
|
+
};
|
|
1692
|
+
|
|
1623
1693
|
/**
|
|
1624
1694
|
* This is a decorator that will tell the decorated class what dbTable to use
|
|
1625
1695
|
* @param dbArg
|
|
@@ -1682,6 +1752,7 @@ export function managed<TManager extends IManager>(
|
|
|
1682
1752
|
bindingOptions?.toleratedIndexNames,
|
|
1683
1753
|
);
|
|
1684
1754
|
},
|
|
1755
|
+
!managerArg,
|
|
1685
1756
|
);
|
|
1686
1757
|
Object.defineProperty(constructor, 'manager', {
|
|
1687
1758
|
get(this: unknown) { return getManager(this); },
|
|
@@ -2,6 +2,7 @@ import type * as plugins from './plugins.js';
|
|
|
2
2
|
import type { INormalizedCollectionModelSchema } from './classes.collection.js';
|
|
3
3
|
import type { SmartdataDb } from './classes.db.js';
|
|
4
4
|
import { SmartdataPersistenceError } from './classes.persistence.js';
|
|
5
|
+
import { resolvesSamePersistencePolicies } from './classes.ordinarypersistence.js';
|
|
5
6
|
|
|
6
7
|
export type TSmartdataCollectionTopologyStatus =
|
|
7
8
|
| 'absent'
|
|
@@ -228,18 +229,44 @@ const indexValuesEqual = (
|
|
|
228
229
|
rightArg: ISmartdataCollectionTopologyIndex,
|
|
229
230
|
): boolean => JSON.stringify(leftArg) === JSON.stringify(rightArg);
|
|
230
231
|
|
|
232
|
+
const decoratorMetadataSymbol = (Symbol as unknown as { readonly metadata: symbol }).metadata;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @internal Finds the collection schema binding a model resolves: its own, or
|
|
236
|
+
* the one of the model it extends when it declares nothing of its own. Such an
|
|
237
|
+
* undecorated subclass — `bindDocToManager()` creates one per manager — is
|
|
238
|
+
* described exactly by the inherited schema. A subclass that declares decorator
|
|
239
|
+
* metadata or a persistence policy without a binding of its own is not, so it
|
|
240
|
+
* resolves none.
|
|
241
|
+
*/
|
|
242
|
+
export const findCollectionModelSchemaResolver = (
|
|
243
|
+
constructorArg: unknown,
|
|
244
|
+
): TCollectionModelSchemaResolver | undefined => {
|
|
245
|
+
if (typeof constructorArg !== 'function') {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
let owner: unknown = constructorArg;
|
|
249
|
+
while (typeof owner === 'function') {
|
|
250
|
+
if (Object.hasOwn(owner, collectionModelSchemaResolverSymbol)) {
|
|
251
|
+
const resolver = (owner as ICollectionTopologyModelConstructor)[collectionModelSchemaResolverSymbol];
|
|
252
|
+
return typeof resolver === 'function' &&
|
|
253
|
+
resolvesSamePersistencePolicies(constructorArg, owner)
|
|
254
|
+
? resolver
|
|
255
|
+
: undefined;
|
|
256
|
+
}
|
|
257
|
+
if (Object.hasOwn(owner, decoratorMetadataSymbol)) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
owner = Object.getPrototypeOf(owner);
|
|
261
|
+
}
|
|
262
|
+
return undefined;
|
|
263
|
+
};
|
|
264
|
+
|
|
231
265
|
const getSchemaResolver = (
|
|
232
266
|
constructorArg: ICollectionTopologyModelConstructor,
|
|
233
267
|
): TCollectionModelSchemaResolver => {
|
|
234
|
-
const resolver = constructorArg
|
|
235
|
-
if (
|
|
236
|
-
typeof constructorArg !== 'function' ||
|
|
237
|
-
!Object.prototype.hasOwnProperty.call(
|
|
238
|
-
constructorArg,
|
|
239
|
-
collectionModelSchemaResolverSymbol,
|
|
240
|
-
) ||
|
|
241
|
-
typeof resolver !== 'function'
|
|
242
|
-
) {
|
|
268
|
+
const resolver = findCollectionModelSchemaResolver(constructorArg);
|
|
269
|
+
if (resolver === undefined) {
|
|
243
270
|
throw new SmartdataPersistenceError(
|
|
244
271
|
'invalid_configuration',
|
|
245
272
|
`Model "${constructorArg?.name || 'unknown'}" has no collection schema binding.`,
|
|
@@ -77,7 +77,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
|
|
77
77
|
private startHeartbeat = async () => {
|
|
78
78
|
while (this.ownInstance.data.status !== 'stopped') {
|
|
79
79
|
await this.sendHeartbeat();
|
|
80
|
-
await plugins.
|
|
80
|
+
await plugins.smartpromise.delayForRandom(5000, 10000);
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
|
|
@@ -179,7 +179,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
|
|
179
179
|
logger.log('info', 'bidding code stored.');
|
|
180
180
|
});
|
|
181
181
|
logger.log('info', `bidding for leadership...`);
|
|
182
|
-
await plugins.
|
|
182
|
+
await plugins.smartpromise.delayFor(plugins.smarttime.getMilliSecondsFromUnits({ seconds: 5 }));
|
|
183
183
|
await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => {
|
|
184
184
|
let biddingInstances = await DistributedClass.getInstances({});
|
|
185
185
|
biddingInstances = biddingInstances.filter(
|
|
@@ -195,7 +195,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
|
|
195
195
|
this.ownInstance.data.elected = false;
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
await plugins.
|
|
198
|
+
await plugins.smartpromise.delayFor(5000);
|
|
199
199
|
logger.log('info', `settling with status elected = ${this.ownInstance.data.elected}`);
|
|
200
200
|
this.ownInstance.data.status = 'settled';
|
|
201
201
|
await this.ownInstance.save();
|
|
@@ -221,7 +221,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
|
|
221
221
|
* all instances that requested this task
|
|
222
222
|
*/
|
|
223
223
|
requestingDistibutedInstanceIds: string[];
|
|
224
|
-
responseTimeout: plugins.
|
|
224
|
+
responseTimeout: plugins.smartpromise.Timeout<any>;
|
|
225
225
|
}> = [];
|
|
226
226
|
|
|
227
227
|
this.distributedWatcher.changeSubject.subscribe({
|
|
@@ -243,7 +243,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
|
|
243
243
|
await instance.delete();
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
|
-
await plugins.
|
|
246
|
+
await plugins.smartpromise.delayFor(10000);
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
@@ -260,7 +260,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
|
|
260
260
|
this.ownInstance.data.taskRequests.push(taskRequestArg);
|
|
261
261
|
await this.ownInstance.save();
|
|
262
262
|
});
|
|
263
|
-
await plugins.
|
|
263
|
+
await plugins.smartpromise.delayFor(10000);
|
|
264
264
|
const result = await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => {
|
|
265
265
|
await this.ownInstance.updateFromDb();
|
|
266
266
|
const taskRequestResult = this.ownInstance.data.taskRequestResults.find((resultItem) => {
|
|
@@ -291,7 +291,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
|
|
291
291
|
}
|
|
292
292
|
Object.assign(existingInfoBasis, infoBasisArg);
|
|
293
293
|
await this.ownInstance.save();
|
|
294
|
-
plugins.
|
|
294
|
+
plugins.smartpromise.delayFor(60000).then(() => {
|
|
295
295
|
this.asyncExecutionStack.getExclusiveExecutionSlot(async () => {
|
|
296
296
|
const indexToRemove = this.ownInstance.data.taskRequests.indexOf(existingInfoBasis);
|
|
297
297
|
if (indexToRemove >= 0) {
|
|
@@ -246,7 +246,7 @@ export class EasyStore<T> {
|
|
|
246
246
|
public async cleanUpEphemeral() {
|
|
247
247
|
// Clean up ephemeral data periodically while connected
|
|
248
248
|
while (this.smartdataDbRef.status === 'connected') {
|
|
249
|
-
await plugins.
|
|
249
|
+
await plugins.smartpromise.delayFor(60000); // Check every minute
|
|
250
250
|
// TODO: Implement actual cleanup logic for ephemeral data
|
|
251
251
|
// For now, this prevents the infinite CPU loop
|
|
252
252
|
}
|
|
@@ -28,6 +28,14 @@ const exactSymbol = Symbol.for('@push.rocks/smartdata.exactPersistencePolicy');
|
|
|
28
28
|
export const hasExactPersistencePolicy = (modelArg: any): boolean =>
|
|
29
29
|
Boolean(modelArg?.[exactSymbol]);
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* @internal Whether two models resolve the same ordinary and exact persistence
|
|
33
|
+
* policies, so one model's collection schema describes the other.
|
|
34
|
+
*/
|
|
35
|
+
export const resolvesSamePersistencePolicies = (leftArg: object, rightArg: object): boolean =>
|
|
36
|
+
Reflect.get(leftArg, policySymbol) === Reflect.get(rightArg, policySymbol) &&
|
|
37
|
+
Reflect.get(leftArg, exactSymbol) === Reflect.get(rightArg, exactSymbol);
|
|
38
|
+
|
|
31
39
|
export const getOrdinaryPersistencePolicy = (modelArg: any): IOrdinaryPersistencePolicy | undefined => {
|
|
32
40
|
const policy = modelArg?.[policySymbol] as IOrdinaryPersistencePolicy | undefined;
|
|
33
41
|
if (policy && modelArg[exactSymbol]) {
|
|
@@ -67,7 +67,7 @@ export class SmartdataDbWatcher<T = any> extends EventEmitter {
|
|
|
67
67
|
this.changeStream.on('change', this.onChange);
|
|
68
68
|
this.changeStream.on('error', this.onStreamError);
|
|
69
69
|
// Signal readiness after one tick
|
|
70
|
-
plugins.
|
|
70
|
+
plugins.smartpromise.delayFor(0).then(() => {
|
|
71
71
|
this.readyDeferred.resolve();
|
|
72
72
|
});
|
|
73
73
|
}
|
package/ts/nosqldb/plugins.ts
CHANGED
|
@@ -5,7 +5,6 @@ export { tsclass };
|
|
|
5
5
|
|
|
6
6
|
// @pushrocks scope
|
|
7
7
|
import * as lik from '@push.rocks/lik';
|
|
8
|
-
import * as smartdelay from '@push.rocks/smartdelay';
|
|
9
8
|
import * as smartlog from '@push.rocks/smartlog';
|
|
10
9
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
11
10
|
import * as smartrx from '@push.rocks/smartrx';
|
|
@@ -21,7 +20,6 @@ import * as nodeNet from 'node:net';
|
|
|
21
20
|
|
|
22
21
|
export {
|
|
23
22
|
lik,
|
|
24
|
-
smartdelay,
|
|
25
23
|
smartpromise,
|
|
26
24
|
smartlog,
|
|
27
25
|
smartrx,
|
|
@@ -301,7 +301,7 @@ export class ClickhouseTable<T extends Record<string, any>> {
|
|
|
301
301
|
'SELECT count() AS cnt FROM system.mutations WHERE is_done = 0 AND database = {database:String} AND table = {table:String}',
|
|
302
302
|
{ database: this.options.database, table: this.options.tableName }, { signal: operation.signal });
|
|
303
303
|
if (BigInt(rows[0]?.cnt ?? 0) === 0n) return;
|
|
304
|
-
await plugins.
|
|
304
|
+
await plugins.smartpromise.delayFor(100);
|
|
305
305
|
}
|
|
306
306
|
} finally { operation.dispose(); }
|
|
307
307
|
}
|
|
@@ -83,7 +83,7 @@ export class SmartClickHouseDb {
|
|
|
83
83
|
while (true) {
|
|
84
84
|
operation.check();
|
|
85
85
|
if (await this.clickhouseHttpClient.ping({ signal: operation.signal })) return;
|
|
86
|
-
await plugins.
|
|
86
|
+
await plugins.smartpromise.delayFor(100, null, this.options.unref);
|
|
87
87
|
}
|
|
88
88
|
} finally { operation.dispose(); }
|
|
89
89
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import * as smartdelay from '@push.rocks/smartdelay';
|
|
2
1
|
import * as smartobject from '@push.rocks/smartobject';
|
|
3
2
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
4
3
|
import * as smartrx from '@push.rocks/smartrx';
|
|
5
|
-
export {
|
|
4
|
+
export { smartobject, smartpromise, smartrx };
|