@harperfast/harper-pro 5.0.7 → 5.0.9
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/core/bin/status.js +2 -2
- package/core/bin/stop.js +5 -6
- package/core/components/OptionsWatcher.ts +9 -1
- package/core/dataLayer/harperBridge/TableSizeObject.ts +35 -0
- package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.ts +24 -0
- package/core/index.ts +113 -0
- package/core/package-lock.json +6 -6
- package/core/resources/DatabaseTransaction.ts +8 -3
- package/core/resources/RecordEncoder.ts +11 -3
- package/core/resources/Table.ts +13 -2
- package/core/resources/blob.ts +7 -2
- package/core/resources/databases.ts +2 -1
- package/core/security/jsLoader.ts +17 -5
- package/core/security/keys.js +1 -1
- package/core/server/DurableSubscriptionsSession.ts +1 -0
- package/core/server/serverHelpers/serverUtilities.ts +2 -5
- package/core/utility/environment/systemInformation.ts +698 -0
- package/core/utility/operation_authorization.js +2 -5
- package/dist/core/bin/status.js +2 -2
- package/dist/core/bin/status.js.map +1 -1
- package/dist/core/bin/stop.js +5 -5
- package/dist/core/bin/stop.js.map +1 -1
- package/dist/core/components/OptionsWatcher.js +8 -1
- package/dist/core/components/OptionsWatcher.js.map +1 -1
- package/dist/core/dataLayer/harperBridge/TableSizeObject.js +32 -0
- package/dist/core/dataLayer/harperBridge/TableSizeObject.js.map +1 -0
- package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +18 -19
- package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js.map +1 -1
- package/dist/core/globals.js +7 -4
- package/dist/core/globals.js.map +1 -1
- package/dist/core/resources/DatabaseTransaction.js +6 -1
- package/dist/core/resources/DatabaseTransaction.js.map +1 -1
- package/dist/core/resources/RecordEncoder.js +18 -9
- package/dist/core/resources/RecordEncoder.js.map +1 -1
- package/dist/core/resources/Table.js +13 -2
- package/dist/core/resources/Table.js.map +1 -1
- package/dist/core/resources/blob.js +5 -2
- package/dist/core/resources/blob.js.map +1 -1
- package/dist/core/resources/databases.js +2 -1
- package/dist/core/resources/databases.js.map +1 -1
- package/dist/core/security/jsLoader.js +19 -2
- package/dist/core/security/jsLoader.js.map +1 -1
- package/dist/core/security/keys.js +1 -1
- package/dist/core/security/keys.js.map +1 -1
- package/dist/core/server/DurableSubscriptionsSession.js +2 -0
- package/dist/core/server/DurableSubscriptionsSession.js.map +1 -1
- package/dist/core/server/serverHelpers/serverUtilities.js +2 -2
- package/dist/core/server/serverHelpers/serverUtilities.js.map +1 -1
- package/dist/core/utility/environment/systemInformation.js +359 -219
- package/dist/core/utility/environment/systemInformation.js.map +1 -1
- package/dist/core/utility/operation_authorization.js +2 -2
- package/dist/core/utility/operation_authorization.js.map +1 -1
- package/dist/replication/replicationConnection.js +18 -8
- package/dist/replication/replicationConnection.js.map +1 -1
- package/dist/security/certificate.js +1 -1
- package/dist/security/certificate.js.map +1 -1
- package/npm-shrinkwrap.json +6 -6
- package/package.json +2 -2
- package/replication/replicationConnection.ts +34 -24
- package/security/certificate.ts +1 -1
- package/studio/web/assets/{index-C0And10y.js → index-DL0ibcSu.js} +2 -2
- package/studio/web/assets/{index-C0And10y.js.map → index-DL0ibcSu.js.map} +1 -1
- package/studio/web/index.html +1 -1
- package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js +0 -25
- package/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +0 -34
- package/core/index.d.ts +0 -56
- package/core/index.js +0 -41
- package/core/utility/environment/systemInformation.js +0 -355
- package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js +0 -24
- package/dist/core/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js.map +0 -1
- package/dist/core/index.js +0 -42
- package/dist/core/index.js.map +0 -1
package/core/bin/status.js
CHANGED
|
@@ -6,7 +6,7 @@ const YAML = require('yaml');
|
|
|
6
6
|
|
|
7
7
|
const hdbTerms = require('../utility/hdbTerms.ts');
|
|
8
8
|
const hdbLog = require('../utility/logging/harper_logger.js');
|
|
9
|
-
const
|
|
9
|
+
const systemInformation = require('../utility/environment/systemInformation.ts');
|
|
10
10
|
const envMgr = require('../utility/environment/environmentManager.js');
|
|
11
11
|
const installation = require('../utility/installation.ts');
|
|
12
12
|
envMgr.initSync();
|
|
@@ -51,7 +51,7 @@ async function status() {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Check the saved pid against any running hdb processes
|
|
54
|
-
const hdbSysInfo = await
|
|
54
|
+
const hdbSysInfo = await systemInformation.getHDBProcessInfo();
|
|
55
55
|
for (const proc of hdbSysInfo.core) {
|
|
56
56
|
if (proc.pid === hdbPid) {
|
|
57
57
|
status.harperdb.status = STATUSES.RUNNING;
|
package/core/bin/stop.js
CHANGED
|
@@ -4,7 +4,7 @@ const hdbLogger = require('../utility/logging/harper_logger.js');
|
|
|
4
4
|
const util = require('util');
|
|
5
5
|
const childProcess = require('child_process');
|
|
6
6
|
const exec = util.promisify(childProcess.exec);
|
|
7
|
-
const
|
|
7
|
+
const systemInformation = require('../utility/environment/systemInformation.ts');
|
|
8
8
|
|
|
9
9
|
const STOP_MSG = 'Stopping Harper Pro.';
|
|
10
10
|
|
|
@@ -14,9 +14,8 @@ async function stop() {
|
|
|
14
14
|
console.log(STOP_MSG);
|
|
15
15
|
hdbLogger.notify(STOP_MSG);
|
|
16
16
|
|
|
17
|
-
const processes = await
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
17
|
+
const processes = await systemInformation.getHDBProcessInfo();
|
|
18
|
+
for (const { pid } of processes.core) {
|
|
19
|
+
exec(`kill ${pid}`);
|
|
20
|
+
}
|
|
22
21
|
}
|
|
@@ -178,7 +178,9 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
178
178
|
// First, ensure current and new config values are Config objects (not null, undefined, or a primitive)
|
|
179
179
|
if (!this.#isConfig(currentConfigValue) || !this.#isConfig(newConfigValue)) {
|
|
180
180
|
// If either is not a config, then just set as there is no need to diff/merge
|
|
181
|
-
|
|
181
|
+
if (!isDeepStrictEqual(currentConfigValue, newConfigValue)) {
|
|
182
|
+
this.#setValue(prevKeys, newConfigValue);
|
|
183
|
+
}
|
|
182
184
|
return;
|
|
183
185
|
}
|
|
184
186
|
|
|
@@ -256,6 +258,12 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
256
258
|
throw new InvalidValueTypeError(keys, value);
|
|
257
259
|
}
|
|
258
260
|
|
|
261
|
+
if (keys.length === 0) {
|
|
262
|
+
this.#scopedConfig = value;
|
|
263
|
+
this.emit('change', keys, value, this.#scopedConfig);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
259
267
|
let obj: ConfigValue = this.#scopedConfig;
|
|
260
268
|
|
|
261
269
|
for (const key of keys.slice(0, -1)) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the table size entry for a RocksDB or LMDB table.
|
|
3
|
+
*/
|
|
4
|
+
export class TableSizeObject {
|
|
5
|
+
schema: string;
|
|
6
|
+
table: string;
|
|
7
|
+
tableSize: number;
|
|
8
|
+
recordCount: number;
|
|
9
|
+
transactionLogSize: number;
|
|
10
|
+
transactionLogRecordCount?: number;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param schema - The schema of the table
|
|
14
|
+
* @param table - The name of the table
|
|
15
|
+
* @param tableSize - The data size of the table in bytes
|
|
16
|
+
* @param recordCount - The number of entries in the table
|
|
17
|
+
* @param transactionLogSize - The number of entries in the transaction log
|
|
18
|
+
* @param transactionLogRecordCount - The data size of the transaction log in bytes
|
|
19
|
+
*/
|
|
20
|
+
constructor(
|
|
21
|
+
schema: string,
|
|
22
|
+
table: string,
|
|
23
|
+
tableSize: number = 0,
|
|
24
|
+
recordCount: number = 0,
|
|
25
|
+
transactionLogSize: number = 0,
|
|
26
|
+
transactionLogRecordCount?: number
|
|
27
|
+
) {
|
|
28
|
+
this.schema = schema;
|
|
29
|
+
this.table = table;
|
|
30
|
+
this.tableSize = tableSize;
|
|
31
|
+
this.recordCount = recordCount;
|
|
32
|
+
this.transactionLogSize = transactionLogSize;
|
|
33
|
+
this.transactionLogRecordCount = transactionLogRecordCount;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TableSizeObject } from '../../TableSizeObject.ts';
|
|
2
|
+
import logger from '../../../../utility/logging/harper_logger.js';
|
|
3
|
+
import type { Table } from '../../../../resources/databases.ts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Calculates the number of entries & data size in bytes for a table & its transaction log
|
|
7
|
+
* @param table
|
|
8
|
+
* @returns {TableSizeObject}
|
|
9
|
+
*/
|
|
10
|
+
export function lmdbGetTableSize(table: Table) {
|
|
11
|
+
const tableStats = new TableSizeObject(table.databaseName, table.tableName);
|
|
12
|
+
try {
|
|
13
|
+
const dbiStat = table.primaryStore.getStats();
|
|
14
|
+
|
|
15
|
+
//get the txn log record count
|
|
16
|
+
const txnDbiStat = table.auditStore?.getStats();
|
|
17
|
+
|
|
18
|
+
tableStats.recordCount = dbiStat.entryCount;
|
|
19
|
+
tableStats.transactionLogRecordCount = txnDbiStat.entryCount;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
logger.warn(`unable to stat table dbi due to ${e}`);
|
|
22
|
+
}
|
|
23
|
+
return tableStats;
|
|
24
|
+
}
|
package/core/index.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Prevents server from starting in worker threads if this was directly imported from a non-server user thread
|
|
2
|
+
import workerThreads from 'node:worker_threads';
|
|
3
|
+
if (!workerThreads.isMainThread) {
|
|
4
|
+
// @ts-expect-error - Idk this has been here for a while. Types say its readonly, but that must not be true.
|
|
5
|
+
if (!workerThreads.workerData) workerThreads.workerData = {};
|
|
6
|
+
workerThreads.workerData.noServerStart = true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Regular exports (don't require the same initialization as the globals at the end of this file do)
|
|
10
|
+
export { RequestTarget } from './resources/RequestTarget.ts';
|
|
11
|
+
export { getContext, getResponse, getUser } from './security/jsLoader.ts';
|
|
12
|
+
|
|
13
|
+
// Type only exports.
|
|
14
|
+
// Anything exported here will only be available as TypeScript types, not as values.
|
|
15
|
+
// For exporting values see below.
|
|
16
|
+
export type {
|
|
17
|
+
Query,
|
|
18
|
+
Context,
|
|
19
|
+
Session,
|
|
20
|
+
SourceContext,
|
|
21
|
+
SubscriptionRequest,
|
|
22
|
+
RequestTargetOrId,
|
|
23
|
+
ResourceInterface,
|
|
24
|
+
} from './resources/ResourceInterface.ts';
|
|
25
|
+
export type { User } from './security/user.ts';
|
|
26
|
+
export type { RecordObject } from './resources/RecordEncoder.ts';
|
|
27
|
+
export type { IterableEventQueue } from './resources/IterableEventQueue.ts';
|
|
28
|
+
export type { Table } from './resources/databases.ts';
|
|
29
|
+
export type { Attribute } from './resources/Table.ts';
|
|
30
|
+
export type { Scope } from './components/Scope.ts';
|
|
31
|
+
export type { FilesOption, FilesOptionObject } from './components/deriveGlobOptions.ts';
|
|
32
|
+
export type { FileAndURLPathConfig } from './components/Component.ts';
|
|
33
|
+
export type { OptionsWatcher, Config, ConfigValue } from './components/OptionsWatcher.ts';
|
|
34
|
+
export type {
|
|
35
|
+
EntryHandler,
|
|
36
|
+
BaseEntry,
|
|
37
|
+
FileEntry,
|
|
38
|
+
EntryEvent,
|
|
39
|
+
AddFileEvent,
|
|
40
|
+
ChangeFileEvent,
|
|
41
|
+
UnlinkFileEvent,
|
|
42
|
+
FileEntryEvent,
|
|
43
|
+
AddDirectoryEvent,
|
|
44
|
+
UnlinkDirectoryEvent,
|
|
45
|
+
DirectoryEntryEvent,
|
|
46
|
+
} from './components/EntryHandler.ts';
|
|
47
|
+
|
|
48
|
+
// Globals and values
|
|
49
|
+
// This section is responsible for creating the CJS exports map (for static analysis)
|
|
50
|
+
// as well as defining the globals and values exports.
|
|
51
|
+
// The stuff exported here are actually functional pieces of code.
|
|
52
|
+
// Importantly, do not import any values directly.
|
|
53
|
+
// For example, `import { tables } from './resources/databases.ts';` is NOT OKAY!
|
|
54
|
+
// This breaks Harper's dynamic runtime assignment of exports
|
|
55
|
+
// You MUST import as a type and then use `export declare const` instead.
|
|
56
|
+
// This results in the types being written to dist/index.d.ts, but not dist/index.js
|
|
57
|
+
|
|
58
|
+
// And for my sanity please keep these alphabetically sorted so we can ensure nothing is missing.
|
|
59
|
+
|
|
60
|
+
import type { contentTypes as ContentTypesImport } from './server/serverHelpers/contentTypes.ts';
|
|
61
|
+
import type { createBlob as CreateBlobImport } from './resources/blob.ts';
|
|
62
|
+
import type { databases as DatabasesImport } from './resources/databases.ts';
|
|
63
|
+
import type { Logger } from './utility/logging/logger.ts';
|
|
64
|
+
import type { operation as OperationImport } from './server/serverHelpers/serverUtilities.ts';
|
|
65
|
+
import type { Resource as ResourceImport } from './resources/Resource.ts';
|
|
66
|
+
import type { server as ServerImport } from './server/Server.ts';
|
|
67
|
+
import type { tables as TablesImport } from './resources/databases.ts';
|
|
68
|
+
type ThreadsImport = unknown[]; // TODO: figure out actual type for this
|
|
69
|
+
import type { transaction as TransactionImport } from './resources/transaction.ts';
|
|
70
|
+
|
|
71
|
+
declare global {
|
|
72
|
+
const contentTypes: typeof ContentTypesImport;
|
|
73
|
+
const createBlob: typeof CreateBlobImport;
|
|
74
|
+
const databases: typeof DatabasesImport;
|
|
75
|
+
const logger: Logger;
|
|
76
|
+
const operation: typeof OperationImport;
|
|
77
|
+
const Resource: typeof ResourceImport;
|
|
78
|
+
const server: typeof ServerImport;
|
|
79
|
+
const tables: typeof TablesImport;
|
|
80
|
+
const threads: ThreadsImport;
|
|
81
|
+
const transaction: typeof TransactionImport;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Declare constant types so these are defined in `index.d.ts`
|
|
85
|
+
export declare const contentTypes: typeof ContentTypesImport;
|
|
86
|
+
export declare const createBlob: typeof CreateBlobImport;
|
|
87
|
+
export declare const databases: typeof DatabasesImport;
|
|
88
|
+
export declare const logger: Logger;
|
|
89
|
+
export declare const operation: typeof OperationImport;
|
|
90
|
+
export declare const Resource: typeof ResourceImport;
|
|
91
|
+
export declare const server: typeof ServerImport;
|
|
92
|
+
export declare const tables: typeof TablesImport;
|
|
93
|
+
export declare const threads: ThreadsImport;
|
|
94
|
+
export declare const transaction: typeof TransactionImport;
|
|
95
|
+
|
|
96
|
+
// Actual define the values on the `exports` for CJS static analysis
|
|
97
|
+
exports.contentTypes = null;
|
|
98
|
+
exports.createBlob = undefined;
|
|
99
|
+
exports.databases = {};
|
|
100
|
+
exports.logger = {};
|
|
101
|
+
exports.operation = undefined;
|
|
102
|
+
exports.Resource = undefined;
|
|
103
|
+
exports.server = {};
|
|
104
|
+
exports.tables = {};
|
|
105
|
+
exports.threads = [];
|
|
106
|
+
exports.transaction = undefined;
|
|
107
|
+
|
|
108
|
+
// And finally assign globals to exports.
|
|
109
|
+
// These values are populated at runtime by `_assignPackageExport()` in their respective modules
|
|
110
|
+
// (e.g. Resource.ts, databases.ts, Server.ts, etc.)
|
|
111
|
+
import { globals } from './server/threads/threadServer.js';
|
|
112
|
+
|
|
113
|
+
Object.assign(exports, globals);
|
package/core/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harper",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.9",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "harper",
|
|
9
|
-
"version": "5.0.
|
|
9
|
+
"version": "5.0.9",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@aws-sdk/client-s3": "^3.1012.0",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"@fastify/autoload": "^6.3.1",
|
|
17
17
|
"@fastify/compress": "^8.3.1",
|
|
18
18
|
"@fastify/cors": "^11.2.0",
|
|
19
|
-
"@fastify/static": "^9.
|
|
19
|
+
"@fastify/static": "^9.1.3",
|
|
20
20
|
"@harperfast/extended-iterable": "^1.0.1",
|
|
21
21
|
"@harperfast/rocksdb-js": "^1.0.1",
|
|
22
22
|
"@turf/area": "6.5.0",
|
|
@@ -2160,9 +2160,9 @@
|
|
|
2160
2160
|
}
|
|
2161
2161
|
},
|
|
2162
2162
|
"node_modules/@fastify/static": {
|
|
2163
|
-
"version": "9.
|
|
2164
|
-
"resolved": "https://registry.npmjs.org/@fastify/static/-/static-9.
|
|
2165
|
-
"integrity": "sha512-
|
|
2163
|
+
"version": "9.1.3",
|
|
2164
|
+
"resolved": "https://registry.npmjs.org/@fastify/static/-/static-9.1.3.tgz",
|
|
2165
|
+
"integrity": "sha512-aXrYtsiryLhRxRNaxNqsn7FUISeb7rB9q4eHUPIot5aeQBLNahnz1m6thzm7JWC1poSGXS9XrX8DvuMivp2hkQ==",
|
|
2166
2166
|
"funding": [
|
|
2167
2167
|
{
|
|
2168
2168
|
"type": "github",
|
|
@@ -256,9 +256,14 @@ export class DatabaseTransaction implements Transaction {
|
|
|
256
256
|
if (!outstandingCommit) {
|
|
257
257
|
outstandingCommit = commitResolution;
|
|
258
258
|
outstandingCommitStart = performance.now();
|
|
259
|
-
outstandingCommit
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
outstandingCommit
|
|
260
|
+
// if `commitResolution` rejects with and `ERR_BUSY` error, the retry logic
|
|
261
|
+
// will correct course, but the reject will still be propagated on the
|
|
262
|
+
// `outstandingCommit` promise and needs to be caught and silenced
|
|
263
|
+
.catch(() => {})
|
|
264
|
+
.finally(() => {
|
|
265
|
+
outstandingCommit = null;
|
|
266
|
+
});
|
|
262
267
|
}
|
|
263
268
|
const completions = [];
|
|
264
269
|
return commitResolution.then(
|
|
@@ -64,8 +64,8 @@ const TRACKED_WRITE_TYPES = new Set(['put', 'patch', 'delete', 'message', 'publi
|
|
|
64
64
|
// WeakMaps are definitely not the fastest form of private properties, but they are the only
|
|
65
65
|
// way to do this with how the objects are frozen for now.
|
|
66
66
|
export const entryMap = new WeakMap<any, Entry>();
|
|
67
|
-
let lastValueEncoding
|
|
68
|
-
|
|
67
|
+
export let lastValueEncoding: Buffer | undefined;
|
|
68
|
+
let timestampNextEncoding = 0,
|
|
69
69
|
metadataInNextEncoding = -1,
|
|
70
70
|
expiresAtNextEncoding = -1,
|
|
71
71
|
residencyIdAtNextEncoding = 0,
|
|
@@ -470,6 +470,7 @@ export function handleLocalTimeForGets(store, rootStore) {
|
|
|
470
470
|
};
|
|
471
471
|
Txn.prototype.done = function () {
|
|
472
472
|
done.call(this);
|
|
473
|
+
this.openTimer = 0; // reset so idle pool time doesn't accumulate toward the stale-open threshold
|
|
473
474
|
if (this.isDone) {
|
|
474
475
|
for (let i = 0; i < trackedTxns.length; i++) {
|
|
475
476
|
const txn = trackedTxns[i].deref();
|
|
@@ -498,7 +499,14 @@ setInterval(() => {
|
|
|
498
499
|
'Read transaction detected that has been open too long (over 15 minutes), ending transaction',
|
|
499
500
|
txn
|
|
500
501
|
);
|
|
501
|
-
|
|
502
|
+
trackedTxns.splice(i--, 1);
|
|
503
|
+
txn.timerTracked = false;
|
|
504
|
+
txn.openTimer = 0;
|
|
505
|
+
try {
|
|
506
|
+
txn.done();
|
|
507
|
+
} catch (error) {
|
|
508
|
+
harperLogger.warn('Unexpected error force-closing stale LMDB read transaction', error);
|
|
509
|
+
}
|
|
502
510
|
} else
|
|
503
511
|
harperLogger.error(
|
|
504
512
|
'Read transaction detected that has been open too long (over one minute), make sure read transactions are quickly closed',
|
package/core/resources/Table.ts
CHANGED
|
@@ -363,6 +363,10 @@ export function makeTable(options) {
|
|
|
363
363
|
// we listen for events by iterating through the async iterator provided by the subscription
|
|
364
364
|
for await (const event of subscription) {
|
|
365
365
|
try {
|
|
366
|
+
if (!event || typeof event !== 'object') {
|
|
367
|
+
logger.error?.('Bad subscription event', event);
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
366
370
|
const firstWrite = event.type === 'transaction' ? event.writes[0] : event;
|
|
367
371
|
if (!firstWrite) {
|
|
368
372
|
logger.error?.('Bad subscription event', event);
|
|
@@ -1425,7 +1429,8 @@ export function makeTable(options) {
|
|
|
1425
1429
|
*/
|
|
1426
1430
|
static evict(id, existingRecord, existingVersion) {
|
|
1427
1431
|
let entry;
|
|
1428
|
-
|
|
1432
|
+
const lmdbTransaction = txnForContext({ transaction: new DatabaseTransaction() });
|
|
1433
|
+
let transaction = lmdbTransaction.getReadTxn();
|
|
1429
1434
|
let options = { transaction };
|
|
1430
1435
|
try {
|
|
1431
1436
|
if (hasSourceGet || audit) {
|
|
@@ -1452,7 +1457,13 @@ export function makeTable(options) {
|
|
|
1452
1457
|
return removeEntry(primaryStore, entry ?? primaryStore.getEntry(id), options);
|
|
1453
1458
|
}
|
|
1454
1459
|
} finally {
|
|
1455
|
-
|
|
1460
|
+
if (primaryStore.ifVersion) {
|
|
1461
|
+
// LMDB: committing the wrapper calls doneReadTxn(), removing it from trackedTxns
|
|
1462
|
+
return lmdbTransaction.commit();
|
|
1463
|
+
}
|
|
1464
|
+
// RocksDB: eviction writes went directly into the raw transaction via options;
|
|
1465
|
+
// commit it directly, as DatabaseTransaction.commit() would abort it (no tracked writes)
|
|
1466
|
+
return transaction?.commit();
|
|
1456
1467
|
}
|
|
1457
1468
|
}
|
|
1458
1469
|
/**
|
package/core/resources/blob.ts
CHANGED
|
@@ -44,6 +44,7 @@ import { HAS_BLOBS } from './auditStore.ts';
|
|
|
44
44
|
import { getHeapStatistics } from 'node:v8';
|
|
45
45
|
import { setTimeout as delay, setImmediate as rest } from 'node:timers/promises';
|
|
46
46
|
import { RocksDatabase } from '@harperfast/rocksdb-js';
|
|
47
|
+
import { _assignPackageExport } from '../globals.js';
|
|
47
48
|
|
|
48
49
|
type StorageInfo = {
|
|
49
50
|
storageIndex: number;
|
|
@@ -503,7 +504,10 @@ export type BlobCreationOptions = {
|
|
|
503
504
|
* can be saved/stored.
|
|
504
505
|
* @param source
|
|
505
506
|
*/
|
|
506
|
-
|
|
507
|
+
export function createBlob(
|
|
508
|
+
source: Uint8Array | NodeJS.ReadableStream | string | Iterable<Uint8Array> | AsyncIterator<Uint8Array>,
|
|
509
|
+
options?: BlobCreationOptions
|
|
510
|
+
): Blob {
|
|
507
511
|
const blob = new FileBackedBlob(options);
|
|
508
512
|
const storageInfo: StorageInfo = {
|
|
509
513
|
storageIndex: 0,
|
|
@@ -521,7 +525,8 @@ global.createBlob = function (source: NodeJS.ReadableStream | NodeJS.Buffer, opt
|
|
|
521
525
|
else if (source?.[Symbol.asyncIterator] || source?.[Symbol.iterator]) storageInfo.source = Readable.from(source);
|
|
522
526
|
else throw new Error('Invalid source type');
|
|
523
527
|
return blob;
|
|
524
|
-
}
|
|
528
|
+
}
|
|
529
|
+
_assignPackageExport('createBlob', createBlob);
|
|
525
530
|
|
|
526
531
|
export function saveBlob(blob: FileBackedBlob, deleteOnFailure = false) {
|
|
527
532
|
let storageInfo = storageInfoForBlob.get(blob);
|
|
@@ -368,7 +368,7 @@ function readRocksMetaDb(path: string, defaultTable?: string, databaseName: stri
|
|
|
368
368
|
if (rootStore) {
|
|
369
369
|
initStores(path, rootStore, databaseName, defaultTable);
|
|
370
370
|
} else {
|
|
371
|
-
rootStore = openRocksDatabase(path, { disableWAL: false }) as RocksDatabaseEx;
|
|
371
|
+
rootStore = openRocksDatabase(path, { disableWAL: false, enableStats: true }) as RocksDatabaseEx;
|
|
372
372
|
rocksdbDatabaseEnvs.set(path, rootStore);
|
|
373
373
|
initStores(path, rootStore, databaseName, defaultTable);
|
|
374
374
|
replayLogs(rootStore, databases[databaseName]);
|
|
@@ -723,6 +723,7 @@ export function database({ database: databaseName, table: tableName }) {
|
|
|
723
723
|
if (!rootStore || rootStore.status === 'closed') {
|
|
724
724
|
rootStore = openRocksDatabase(path, {
|
|
725
725
|
disableWAL: false,
|
|
726
|
+
enableStats: true,
|
|
726
727
|
});
|
|
727
728
|
rocksdbDatabaseEnvs.set(path, rootStore);
|
|
728
729
|
}
|
|
@@ -181,7 +181,13 @@ async function loadModuleWithVM(moduleUrl: string, scope: ApplicationScope, useC
|
|
|
181
181
|
if (parts[0] === 'file:') {
|
|
182
182
|
return specifier;
|
|
183
183
|
}
|
|
184
|
-
|
|
184
|
+
let resolveReferrer = referrer;
|
|
185
|
+
if (referrer.startsWith('file:')) {
|
|
186
|
+
try {
|
|
187
|
+
resolveReferrer = pathToFileURL(realpathSync(fileURLToPath(referrer))).toString();
|
|
188
|
+
} catch {}
|
|
189
|
+
}
|
|
190
|
+
const resolved = createRequire(resolveReferrer).resolve(specifier);
|
|
185
191
|
if (isAbsolute(resolved)) {
|
|
186
192
|
return pathToFileURL(resolved).toString();
|
|
187
193
|
}
|
|
@@ -206,7 +212,13 @@ async function loadModuleWithVM(moduleUrl: string, scope: ApplicationScope, useC
|
|
|
206
212
|
cjsModule.exports = parseJsonModule(source, url);
|
|
207
213
|
return cjsModule;
|
|
208
214
|
}
|
|
209
|
-
|
|
215
|
+
let requireUrl = url;
|
|
216
|
+
if (url.startsWith('file://')) {
|
|
217
|
+
try {
|
|
218
|
+
requireUrl = pathToFileURL(realpathSync(fileURLToPath(url))).toString();
|
|
219
|
+
} catch {}
|
|
220
|
+
}
|
|
221
|
+
const require = createRequire(requireUrl);
|
|
210
222
|
|
|
211
223
|
const cjsRequire = (spec: string) => {
|
|
212
224
|
const resolvedUrl = resolveModule(spec, url);
|
|
@@ -943,13 +955,13 @@ function checkAllowedModulePath(moduleUrl: string, allowedPath?: string): boolea
|
|
|
943
955
|
throw new Error(`Module ${moduleUrl} is not allowed to be imported`);
|
|
944
956
|
}
|
|
945
957
|
|
|
946
|
-
function getContext() {
|
|
958
|
+
export function getContext() {
|
|
947
959
|
return contextStorage.getStore() ?? {};
|
|
948
960
|
}
|
|
949
|
-
function getUser() {
|
|
961
|
+
export function getUser() {
|
|
950
962
|
return contextStorage.getStore()?.user;
|
|
951
963
|
}
|
|
952
|
-
function getResponse() {
|
|
964
|
+
export function getResponse() {
|
|
953
965
|
return contextStorage.getStore()?.response;
|
|
954
966
|
}
|
|
955
967
|
|
package/core/security/keys.js
CHANGED
|
@@ -857,7 +857,7 @@ function createTLSSelector(type, mtlsOptions) {
|
|
|
857
857
|
return SNICallback;
|
|
858
858
|
function SNICallback(servername, cb) {
|
|
859
859
|
// find the matching server name, substituting wildcards for each part of the domain to find matches
|
|
860
|
-
logger.
|
|
860
|
+
logger.debug?.('TLS requested for', servername || '(no SNI)');
|
|
861
861
|
let matchingName = servername;
|
|
862
862
|
while (true) {
|
|
863
863
|
let context = secureContexts.get(matchingName);
|
|
@@ -19,7 +19,7 @@ import restart from '../../bin/restart.js';
|
|
|
19
19
|
import * as util from 'util';
|
|
20
20
|
import insert from '../../dataLayer/insert.js';
|
|
21
21
|
import globalSchema from '../../utility/globalSchema.js';
|
|
22
|
-
import systemInformation from '../../utility/environment/systemInformation.
|
|
22
|
+
import { systemInformation } from '../../utility/environment/systemInformation.ts';
|
|
23
23
|
import jobRunner from '../jobs/jobRunner.js';
|
|
24
24
|
import * as tokenAuthentication from '../../security/tokenAuthentication.ts';
|
|
25
25
|
import * as auth from '../../security/auth.ts';
|
|
@@ -363,10 +363,7 @@ function initializeOperationFunctionMap(): Map<OperationFunctionName, OperationF
|
|
|
363
363
|
opFuncMap.set(terms.OPERATIONS_ENUM.RESTART, new OperationFunctionObject(restart.restart));
|
|
364
364
|
opFuncMap.set(terms.OPERATIONS_ENUM.RESTART_SERVICE, new OperationFunctionObject(executeJob, restart.restartService));
|
|
365
365
|
opFuncMap.set(terms.OPERATIONS_ENUM.CATCHUP, new OperationFunctionObject(catchup));
|
|
366
|
-
opFuncMap.set(
|
|
367
|
-
terms.OPERATIONS_ENUM.SYSTEM_INFORMATION,
|
|
368
|
-
new OperationFunctionObject(systemInformation.systemInformation)
|
|
369
|
-
);
|
|
366
|
+
opFuncMap.set(terms.OPERATIONS_ENUM.SYSTEM_INFORMATION, new OperationFunctionObject(systemInformation));
|
|
370
367
|
opFuncMap.set(
|
|
371
368
|
terms.OPERATIONS_ENUM.DELETE_AUDIT_LOGS_BEFORE,
|
|
372
369
|
new OperationFunctionObject(executeJob, delete_.deleteAuditLogsBefore)
|