@delali/narsil 0.2.3-next.32 → 0.2.3-next.34
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/{chunk-C6VVLMRX.mjs → chunk-36ER4WCG.mjs} +1 -0
- package/dist/{chunk-TEAJO7CU.mjs → chunk-GN7KF675.mjs} +10 -2
- package/dist/{chunk-MFFAJ2NR.mjs → chunk-GODECMDT.mjs} +1 -1
- package/dist/distribution/coordinator/etcd.d.ts +1 -1
- package/dist/distribution/coordinator/etcd.mjs +94 -15
- package/dist/distribution/coordinator/in-memory.d.ts +1 -1
- package/dist/distribution/coordinator/in-memory.mjs +10 -3
- package/dist/distribution/transport/grpc.mjs +2 -2
- package/dist/distribution/transport/in-memory.mjs +1 -1
- package/dist/distribution/transport/tcp.mjs +2 -2
- package/dist/distribution.d.ts +2 -2
- package/dist/distribution.mjs +1821 -1161
- package/dist/index.mjs +2 -2
- package/dist/persistence/durability/checkpoint-worker.mjs +2 -2
- package/dist/{types-Bfhhnh3G.d.ts → types-BhdINMtE.d.ts} +2 -0
- package/package.json +1 -1
|
@@ -35,6 +35,7 @@ var ReplicationMessageTypes = {
|
|
|
35
35
|
SNAPSHOT_CHUNK: "replication.snapshot_chunk",
|
|
36
36
|
SNAPSHOT_END: "replication.snapshot_end",
|
|
37
37
|
SNAPSHOT_SYNC_REQUEST: "replication.snapshot_sync_request",
|
|
38
|
+
INSYNC_ADD: "replication.insync_add",
|
|
38
39
|
INSYNC_REMOVE: "replication.insync_remove",
|
|
39
40
|
INSYNC_CONFIRM: "replication.insync_confirm"
|
|
40
41
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReplicationMessageTypes } from './chunk-
|
|
1
|
+
import { ReplicationMessageTypes } from './chunk-36ER4WCG.mjs';
|
|
2
2
|
import { getNestedValue, getLanguage, extractVectorFieldsFromSchema, createDirectExecutor, createPartitionRouter, clampRowCount, DEFAULT_PAGE_SIZE, validateSchema, validateVectorPromotion, collectQueryTermStats, createPartitionManager, createVectorIndex, flattenSchema, isTextFieldType, requireWithinResultWindow, normalizeSort, sortSignatureOf, requireSortableFields, fanOutQuery, applySorting, applyPagination, resolveProjection, tokenize, decodePageCursor, requireMatchingCursor, encodePageCursor, resolveIndexAnalysis, deserializePayloadV2, deserializePayloadV1, validateRequiredFields, mergePartitionStats, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, createPartitionIndex, fnv1a, createWorkerPool, validateDocument, validateDocumentStrict, createFrozenSegment, detectRuntime, serializeMetadata, isNodeMainThread, spawnNodeWorker, createSharedFrozenSegment, buildCompactedSegmentPayload, freezeSegmentShared, deserializeMetadata, isCompositePartition, kWayMerge } from './chunk-RO4EFWE6.mjs';
|
|
3
3
|
import { crc32, crc32Init, crc32Update, crc32Final } from './chunk-KMMJMDUA.mjs';
|
|
4
4
|
import { compareCodePoints, compareComparableKeys } from './chunk-BFIH7OV5.mjs';
|
|
@@ -2565,6 +2565,14 @@ function createForwardBatchResultMessage(payload, sourceId, requestId) {
|
|
|
2565
2565
|
payload: encode(payload)
|
|
2566
2566
|
};
|
|
2567
2567
|
}
|
|
2568
|
+
function createInsyncAddMessage(payload, sourceId) {
|
|
2569
|
+
return {
|
|
2570
|
+
type: ReplicationMessageTypes.INSYNC_ADD,
|
|
2571
|
+
sourceId,
|
|
2572
|
+
requestId: generateId(),
|
|
2573
|
+
payload: encode(payload)
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2568
2576
|
function createInsyncRemoveMessage(payload, sourceId) {
|
|
2569
2577
|
return {
|
|
2570
2578
|
type: ReplicationMessageTypes.INSYNC_REMOVE,
|
|
@@ -9321,4 +9329,4 @@ async function createNarsil(config) {
|
|
|
9321
9329
|
// src/index.ts
|
|
9322
9330
|
var VERSION = "0.1.0";
|
|
9323
9331
|
|
|
9324
|
-
export { DEFAULT_SUGGEST_LIMIT, MAX_INDEX_NAME_LENGTH, MAX_PARTITION_COUNT, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, SUGGEST_OVERSAMPLE_FACTOR, SUGGEST_OVERSAMPLE_PADDING, VERSION, WIRE_BATCH_BUDGET, applyDeleteEntry, applyIndexEntry, chunkByBudget, clampLimit, computeEntryChecksum, createAckMessage, createDurableDirectory, createEngineCore, createEngineIndex, createEntryBatchMessage, createEntryMessage, createForwardBatchMessage, createForwardBatchResultMessage, createForwardMessage, createInsyncConfirmMessage, createInsyncRemoveMessage, createNarsil, createNarsilFromCore, getIndexMetadata, indexConfigKey, now, putIndexMetadata, runEngineListDocuments, runEnginePreflight, runEngineQuery, runEngineQueryStats, runEngineSuggest, validateAckPayload, validateEntryBatchPayload, validateEntryPayload, validateForwardBatchPayload, validateForwardBatchResultPayload, validateIndexName, validateInsyncConfirmPayload, validateReplicationEntry, writeSegmentedCheckpoint };
|
|
9332
|
+
export { DEFAULT_SUGGEST_LIMIT, MAX_INDEX_NAME_LENGTH, MAX_PARTITION_COUNT, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, SUGGEST_OVERSAMPLE_FACTOR, SUGGEST_OVERSAMPLE_PADDING, VERSION, WIRE_BATCH_BUDGET, applyDeleteEntry, applyIndexEntry, chunkByBudget, clampLimit, computeEntryChecksum, createAckMessage, createDurableDirectory, createEngineCore, createEngineIndex, createEntryBatchMessage, createEntryMessage, createForwardBatchMessage, createForwardBatchResultMessage, createForwardMessage, createInsyncAddMessage, createInsyncConfirmMessage, createInsyncRemoveMessage, createNarsil, createNarsilFromCore, getIndexMetadata, indexConfigKey, now, putIndexMetadata, runEngineListDocuments, runEnginePreflight, runEngineQuery, runEngineQueryStats, runEngineSuggest, validateAckPayload, validateEntryBatchPayload, validateEntryPayload, validateForwardBatchPayload, validateForwardBatchResultPayload, validateIndexName, validateInsyncConfirmPayload, validateReplicationEntry, writeSegmentedCheckpoint };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MAX_MESSAGE_SIZE_BYTES, TransportError, TransportErrorCodes } from './chunk-
|
|
1
|
+
import { MAX_MESSAGE_SIZE_BYTES, TransportError, TransportErrorCodes } from './chunk-36ER4WCG.mjs';
|
|
2
2
|
import { encode, decode } from '@msgpack/msgpack';
|
|
3
3
|
|
|
4
4
|
// src/distribution/transport/tcp/types.ts
|
|
@@ -39,10 +39,22 @@ function extractSuffix(fullKey, prefix) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// src/distribution/coordinator/etcd/leases.ts
|
|
42
|
+
function payloadsMatch(left, right) {
|
|
43
|
+
if (left === null || left.byteLength !== right.byteLength) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
for (let index = 0; index < left.byteLength; index++) {
|
|
47
|
+
if (left[index] !== right[index]) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
42
53
|
var LeaseManager = class {
|
|
43
54
|
leases = /* @__PURE__ */ new Map();
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
keyLocks = /* @__PURE__ */ new Map();
|
|
56
|
+
track(key, lease, nodeId, payload = null) {
|
|
57
|
+
this.leases.set(key, { lease, nodeId, key, payload });
|
|
46
58
|
}
|
|
47
59
|
get(key) {
|
|
48
60
|
return this.leases.get(key);
|
|
@@ -54,6 +66,10 @@ var LeaseManager = class {
|
|
|
54
66
|
}
|
|
55
67
|
return entry;
|
|
56
68
|
}
|
|
69
|
+
holdsPayload(key, payload) {
|
|
70
|
+
const entry = this.leases.get(key);
|
|
71
|
+
return entry !== void 0 && payloadsMatch(entry.payload, payload);
|
|
72
|
+
}
|
|
57
73
|
remove(key) {
|
|
58
74
|
const entry = this.leases.get(key);
|
|
59
75
|
if (entry !== void 0) {
|
|
@@ -61,6 +77,23 @@ var LeaseManager = class {
|
|
|
61
77
|
}
|
|
62
78
|
return entry;
|
|
63
79
|
}
|
|
80
|
+
runExclusively(key, work) {
|
|
81
|
+
const previous = this.keyLocks.get(key) ?? Promise.resolve();
|
|
82
|
+
const result = previous.then(work, work);
|
|
83
|
+
const settled = result.then(
|
|
84
|
+
() => {
|
|
85
|
+
},
|
|
86
|
+
() => {
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
this.keyLocks.set(key, settled);
|
|
90
|
+
void settled.then(() => {
|
|
91
|
+
if (this.keyLocks.get(key) === settled) {
|
|
92
|
+
this.keyLocks.delete(key);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
64
97
|
async revokeAll() {
|
|
65
98
|
const revokePromises = [];
|
|
66
99
|
for (const [, entry] of this.leases) {
|
|
@@ -113,9 +146,26 @@ function deserializeAllocationTable(data) {
|
|
|
113
146
|
indexName: raw.indexName,
|
|
114
147
|
version: raw.version,
|
|
115
148
|
replicationFactor: typeof raw.replicationFactor === "number" ? raw.replicationFactor : 0,
|
|
116
|
-
assignments:
|
|
149
|
+
assignments: normaliseAssignments(raw.assignments)
|
|
117
150
|
};
|
|
118
151
|
}
|
|
152
|
+
function normaliseAssignments(entries) {
|
|
153
|
+
const assignments = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const pair of entries) {
|
|
155
|
+
if (!Array.isArray(pair) || pair.length < 2) {
|
|
156
|
+
throw new NarsilError(ErrorCodes.CONFIG_INVALID, "AllocationTable holds a malformed assignment entry");
|
|
157
|
+
}
|
|
158
|
+
const [partitionId, assignment] = pair;
|
|
159
|
+
if (typeof partitionId !== "number" || assignment === null || typeof assignment !== "object") {
|
|
160
|
+
throw new NarsilError(ErrorCodes.CONFIG_INVALID, "AllocationTable holds a malformed partition assignment");
|
|
161
|
+
}
|
|
162
|
+
const candidate = assignment;
|
|
163
|
+
const storedCommitPoint = candidate.commitPoint;
|
|
164
|
+
const commitPoint = typeof storedCommitPoint === "number" && Number.isSafeInteger(storedCommitPoint) && storedCommitPoint >= 0 ? storedCommitPoint : 0;
|
|
165
|
+
assignments.set(partitionId, { ...assignment, commitPoint });
|
|
166
|
+
}
|
|
167
|
+
return assignments;
|
|
168
|
+
}
|
|
119
169
|
function serializeNodeRegistration(reg) {
|
|
120
170
|
return new Uint8Array(encode(reg));
|
|
121
171
|
}
|
|
@@ -136,6 +186,38 @@ function deserializeSchema(data) {
|
|
|
136
186
|
return decode(data);
|
|
137
187
|
}
|
|
138
188
|
|
|
189
|
+
// src/distribution/coordinator/etcd/registration.ts
|
|
190
|
+
function writeNodeRegistration(context, registration) {
|
|
191
|
+
return context.leaseManager.runExclusively(context.key, () => writeUnderLease(context, registration));
|
|
192
|
+
}
|
|
193
|
+
async function writeUnderLease(context, registration) {
|
|
194
|
+
const payload = serializeNodeRegistration(registration);
|
|
195
|
+
const data = Buffer.from(payload);
|
|
196
|
+
const tracked = context.leaseManager.getByNodeId(context.key, registration.nodeId);
|
|
197
|
+
if (tracked !== void 0) {
|
|
198
|
+
try {
|
|
199
|
+
await tracked.lease.keepaliveOnce();
|
|
200
|
+
if (context.leaseManager.holdsPayload(context.key, payload)) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
await tracked.lease.put(context.key).value(data).exec();
|
|
204
|
+
context.leaseManager.track(context.key, tracked.lease, registration.nodeId, payload);
|
|
205
|
+
return;
|
|
206
|
+
} catch (_) {
|
|
207
|
+
context.leaseManager.remove(context.key);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const lease = context.client.lease(context.ttlSeconds);
|
|
211
|
+
await lease.grant();
|
|
212
|
+
await lease.put(context.key).value(data).exec();
|
|
213
|
+
const existing = context.leaseManager.get(context.key);
|
|
214
|
+
if (existing !== void 0) {
|
|
215
|
+
await existing.lease.revoke().catch(() => {
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
context.leaseManager.track(context.key, lease, registration.nodeId, payload);
|
|
219
|
+
}
|
|
220
|
+
|
|
139
221
|
// src/distribution/coordinator/etcd/validation.ts
|
|
140
222
|
var MAX_NODE_ID_LENGTH = 255;
|
|
141
223
|
var VALID_PARTITION_STATES = /* @__PURE__ */ new Set(["UNASSIGNED", "INITIALISING", "ACTIVE", "MIGRATING", "DECOMMISSIONING"]);
|
|
@@ -206,18 +288,15 @@ async function createEtcdCoordinator(config) {
|
|
|
206
288
|
async registerNode(registration) {
|
|
207
289
|
assertNotShutdown();
|
|
208
290
|
validateNodeId(registration.nodeId);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
leaseManager.track(key, lease, registration.nodeId);
|
|
291
|
+
await writeNodeRegistration(
|
|
292
|
+
{
|
|
293
|
+
client,
|
|
294
|
+
leaseManager,
|
|
295
|
+
key: keys.node(registration.nodeId),
|
|
296
|
+
ttlSeconds: resolvedConfig.nodeHeartbeatTtlSeconds
|
|
297
|
+
},
|
|
298
|
+
registration
|
|
299
|
+
);
|
|
221
300
|
},
|
|
222
301
|
async deregisterNode(nodeId) {
|
|
223
302
|
assertNotShutdown();
|
|
@@ -2,6 +2,7 @@ import { compareCodePoints } from '../../chunk-BFIH7OV5.mjs';
|
|
|
2
2
|
|
|
3
3
|
// src/distribution/coordinator/in-memory.ts
|
|
4
4
|
var NODE_HEARTBEAT_PREFIX = "_narsil/node/";
|
|
5
|
+
var NODE_HEARTBEAT_TTL_MS = 3e4;
|
|
5
6
|
function bytesEqual(a, b) {
|
|
6
7
|
if (a.byteLength !== b.byteLength) {
|
|
7
8
|
return false;
|
|
@@ -80,16 +81,19 @@ function createInMemoryCoordinator() {
|
|
|
80
81
|
const coordinator = {
|
|
81
82
|
async registerNode(registration) {
|
|
82
83
|
assertNotShutdown();
|
|
84
|
+
const previous = nodes.get(registration.nodeId);
|
|
83
85
|
nodes.set(registration.nodeId, registration);
|
|
84
86
|
const heartbeatKey = `${NODE_HEARTBEAT_PREFIX}${registration.nodeId}`;
|
|
85
|
-
const defaultTtlMs = 3e4;
|
|
86
87
|
clearLeaseEntry(heartbeatKey);
|
|
87
|
-
const timer = createLeaseTimer(heartbeatKey,
|
|
88
|
+
const timer = createLeaseTimer(heartbeatKey, NODE_HEARTBEAT_TTL_MS);
|
|
88
89
|
leases.set(heartbeatKey, {
|
|
89
90
|
nodeId: registration.nodeId,
|
|
90
|
-
expiresAt: Date.now() +
|
|
91
|
+
expiresAt: Date.now() + NODE_HEARTBEAT_TTL_MS,
|
|
91
92
|
timer
|
|
92
93
|
});
|
|
94
|
+
if (previous !== void 0 && registrationsMatch(previous, registration)) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
93
97
|
emitNodeEvent({ type: "node_joined", nodeId: registration.nodeId, registration });
|
|
94
98
|
},
|
|
95
99
|
async deregisterNode(nodeId) {
|
|
@@ -282,5 +286,8 @@ function createInMemoryCoordinator() {
|
|
|
282
286
|
};
|
|
283
287
|
return coordinator;
|
|
284
288
|
}
|
|
289
|
+
function registrationsMatch(left, right) {
|
|
290
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
291
|
+
}
|
|
285
292
|
|
|
286
293
|
export { createInMemoryCoordinator };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { decodeTransportMessage, encodeTransportMessage } from '../../chunk-
|
|
2
|
-
import { TransportError, TransportErrorCodes, MAX_MESSAGE_SIZE_BYTES } from '../../chunk-
|
|
1
|
+
import { decodeTransportMessage, encodeTransportMessage } from '../../chunk-GODECMDT.mjs';
|
|
2
|
+
import { TransportError, TransportErrorCodes, MAX_MESSAGE_SIZE_BYTES } from '../../chunk-36ER4WCG.mjs';
|
|
3
3
|
import { NarsilError, ErrorCodes } from '../../chunk-EMI63EXP.mjs';
|
|
4
4
|
|
|
5
5
|
// src/distribution/transport/grpc/codec.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_TRANSPORT_CONFIG, TransportError, TransportErrorCodes, MAX_MESSAGE_SIZE_BYTES } from '../../chunk-
|
|
1
|
+
import { DEFAULT_TRANSPORT_CONFIG, TransportError, TransportErrorCodes, MAX_MESSAGE_SIZE_BYTES } from '../../chunk-36ER4WCG.mjs';
|
|
2
2
|
|
|
3
3
|
// src/distribution/transport/in-memory.ts
|
|
4
4
|
function createInMemoryNetwork() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_TCP_CONFIG, encodeTransportMessage, encodeFrame, FRAME_TYPE_REQUEST, FrameParser, FRAME_TYPE_RESPONSE, decodeTransportMessage, FRAME_TYPE_STREAM_CHUNK, FRAME_TYPE_STREAM_END } from '../../chunk-
|
|
2
|
-
import { MAX_MESSAGE_SIZE_BYTES, TransportError, TransportErrorCodes } from '../../chunk-
|
|
1
|
+
import { DEFAULT_TCP_CONFIG, encodeTransportMessage, encodeFrame, FRAME_TYPE_REQUEST, FrameParser, FRAME_TYPE_RESPONSE, decodeTransportMessage, FRAME_TYPE_STREAM_CHUNK, FRAME_TYPE_STREAM_END } from '../../chunk-GODECMDT.mjs';
|
|
2
|
+
import { MAX_MESSAGE_SIZE_BYTES, TransportError, TransportErrorCodes } from '../../chunk-36ER4WCG.mjs';
|
|
3
3
|
import { connect as connect$1, createServer as createServer$1 } from 'net';
|
|
4
4
|
import { connect, createServer } from 'tls';
|
|
5
5
|
|
package/dist/distribution.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { N as NarsilConfig } from './config-ChZ7lfqc.js';
|
|
2
|
-
import { A as AllocationTable, N as NodeRole, C as ClusterCoordinator, a as NodeCapacity } from './types-
|
|
3
|
-
export { b as AllocationConstraints, c as AllocationEvent, d as NodeEvent, e as NodeRegistration, P as PartitionAssignment, f as PartitionState, S as SchemaEvent } from './types-
|
|
2
|
+
import { A as AllocationTable, N as NodeRole, C as ClusterCoordinator, a as NodeCapacity } from './types-BhdINMtE.js';
|
|
3
|
+
export { b as AllocationConstraints, c as AllocationEvent, d as NodeEvent, e as NodeRegistration, P as PartitionAssignment, f as PartitionState, S as SchemaEvent } from './types-BhdINMtE.js';
|
|
4
4
|
import { N as NodeTransport } from './types-D5OwhtsQ.js';
|
|
5
5
|
export { L as ListenHandler, R as RespondFn, T as TransportConfig, a as TransportMessage } from './types-D5OwhtsQ.js';
|
|
6
6
|
import { a as NarsilEventMap, N as Narsil } from './engine-DScGlT2Z.js';
|