@delali/narsil 0.3.1-next.71 → 0.3.1-next.73
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/README.md +2 -2
- package/dist/adapters/filesystem.mjs +1 -1
- package/dist/adapters/indexeddb.mjs +1 -1
- package/dist/{capabilities-Dt-7B4Wz.d.ts → capabilities-CYeAWYxQ.d.ts} +19 -4
- package/dist/{chunk-3JGWULDF.mjs → chunk-2WLD2NFW.mjs} +5 -5
- package/dist/{chunk-LMO5TJUS.mjs → chunk-3YKWSO54.mjs} +642 -196
- package/dist/{chunk-HWQLTLNG.mjs → chunk-4MQ5F4IL.mjs} +1 -1
- package/dist/{chunk-FVLQ63B7.mjs → chunk-AFKH4ZK3.mjs} +30 -6
- package/dist/{chunk-653BNMAF.mjs → chunk-AK3BLGCI.mjs} +195 -25
- package/dist/{chunk-IOR2K26O.mjs → chunk-CVFAFZSN.mjs} +8000 -4391
- package/dist/{chunk-USKFU7J5.mjs → chunk-I64LXKO3.mjs} +1 -1
- package/dist/{chunk-OI42GWLR.mjs → chunk-LJYTW7GT.mjs} +57 -11
- package/dist/{chunk-2STVUTNA.mjs → chunk-LPBWCHBE.mjs} +194 -13
- package/dist/{chunk-YNVIUGF5.mjs → chunk-PU43WDY4.mjs} +4 -2
- package/dist/{chunk-M76V3OGJ.mjs → chunk-THMSFOJO.mjs} +1289 -1405
- package/dist/{chunk-YJDQ7NLA.mjs → chunk-WVDFG45M.mjs} +93 -95
- package/dist/chunk-XW25X6AU.mjs +614 -0
- package/dist/chunk-ZKRV5M2P.mjs +75 -0
- package/dist/{chunk-P4DSQ6M4.mjs → chunk-ZULSEZCE.mjs} +68 -28
- package/dist/{client-COek5GXK.d.ts → client-D698E5ge.d.ts} +77 -26
- package/dist/client.d.ts +9 -9
- package/dist/client.mjs +45 -22
- package/dist/{config-rBpbgTw8.d.ts → config-Bv8etwUZ.d.ts} +11 -4
- package/dist/{config-Dfanyqqt.d.ts → config-QXU3HMpq.d.ts} +26 -2
- package/dist/direct-executor-5SRDFZAS.mjs +13 -0
- package/dist/distribution/coordinator/etcd.d.ts +29 -16
- package/dist/distribution/coordinator/etcd.mjs +163 -76
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- package/dist/distribution/coordinator/in-memory.mjs +1 -1
- package/dist/distribution/transport/grpc.d.ts +2 -2
- package/dist/distribution/transport/grpc.mjs +22 -2
- package/dist/distribution/transport/in-memory.d.ts +2 -2
- package/dist/distribution/transport/in-memory.mjs +6 -3
- package/dist/distribution/transport/tcp.d.ts +2 -2
- package/dist/distribution/transport/tcp.mjs +40 -16
- package/dist/distribution.d.ts +9 -9
- package/dist/distribution.mjs +682 -388
- package/dist/embeddings/openai.mjs +1 -1
- package/dist/{engine-igk0aMpQ.d.ts → engine-D_OzKZ-6.d.ts} +97 -188
- package/dist/index.browser.mjs +11671 -7427
- package/dist/index.d.ts +27 -8
- package/dist/index.mjs +13 -14
- package/dist/invalidation/filesystem.mjs +1 -1
- package/dist/{memory-C7UMCMH3.d.ts → memory-B4jMmygw.d.ts} +279 -27
- package/dist/pattern-Cledccbl.d.ts +18 -0
- package/dist/pattern.d.ts +22 -0
- package/dist/pattern.mjs +7 -0
- package/dist/persistence/durability/checkpoint-worker.d.ts +41 -17
- package/dist/persistence/durability/checkpoint-worker.mjs +24 -16
- package/dist/react.d.ts +7 -7
- package/dist/react.mjs +1 -1
- package/dist/{schema-Bgzr4g7b.d.ts → schema-BBOCdhND.d.ts} +9 -7
- package/dist/server.d.ts +11 -11
- package/dist/server.mjs +213 -34
- package/dist/{tasks-BZt_zes6.d.ts → tasks-DpgCpW1x.d.ts} +3 -3
- package/dist/{thread-JEVAYETR.mjs → thread-3LNVA43V.mjs} +94 -27
- package/dist/{types-BQDlIvfS.d.ts → types-B3b68nfF.d.ts} +1 -1
- package/dist/{types-gOUqhs2F.d.ts → types-BiUmaiWT.d.ts} +1 -1
- package/dist/{types-D5OwhtsQ.d.ts → types-Cb9kiY5P.d.ts} +1 -1
- package/dist/vector/search-worker.d.ts +1 -1
- package/dist/vector/search-worker.mjs +4 -4
- package/dist/workers/entry.mjs +4 -4
- package/package.json +15 -7
- package/dist/chunk-3L4U6EJQ.mjs +0 -49
- package/dist/chunk-GIVAGD3Q.mjs +0 -25
- package/dist/chunk-IFBKLBGB.mjs +0 -7
- package/dist/direct-executor-GYJEKNV5.mjs +0 -12
- package/dist/serialization/crc32-worker.d.ts +0 -20
- package/dist/serialization/crc32-worker.mjs +0 -62
package/dist/server.mjs
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import { DEFAULT_MAX_RETAINED_TASKS, loadUWebSockets, resolveCors, authorizerFor, createSharedGateBuffer, gateSlotOfWorker, createRouteRunner, corsHeaderReader, createSharedRequestGate, MAIN_THREAD_GATE_SLOT, registerServerRoutes, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_BODY_BYTES, RUNNING_TASK_TTL_MS, DEFAULT_TASK_PAGE_SIZE, TERMINAL_TASK_TTL_MS, TASK_PROGRESS_WRITE_INTERVAL_MS, serializeNarsilError, createVersionHandler, acceptorOf, createDocumentReadHandlers, sendError, respondError, respondJson, MAX_INDEX_TOUCH_INTERVAL_MS, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, clearGateSlot, parseJson, validateCreateIndex, rejectInvalid, validateBatch, serializeBatchResult, validateDocumentBody, validateSuggest, validateQuery, parseTaskListQuery, parseJsonOptional, validateRebalance,
|
|
2
|
-
export { ASYNC_IMPORT_CAPABILITY, INDEX_LIFECYCLE_CAPABILITY, REBUILD_ANALYSIS_CAPABILITY, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, httpStatusForNarsilError } from './chunk-
|
|
3
|
-
import { validateIndexName } from './chunk-
|
|
4
|
-
import { engineCoreOf, providedDocId, resolveVectorText } from './chunk-
|
|
5
|
-
import { detectRuntime } from './chunk-
|
|
6
|
-
import './chunk-
|
|
7
|
-
import './chunk-653BNMAF.mjs';
|
|
1
|
+
import { DEFAULT_MAX_RETAINED_TASKS, loadUWebSockets, resolveCors, authorizerFor, createSharedGateBuffer, gateSlotOfWorker, createRouteRunner, corsHeaderReader, createSharedRequestGate, MAIN_THREAD_GATE_SLOT, registerServerRoutes, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESTORE_BYTES, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_BODY_BYTES, RUNNING_TASK_TTL_MS, DEFAULT_TASK_PAGE_SIZE, TERMINAL_TASK_TTL_MS, TASK_PROGRESS_WRITE_INTERVAL_MS, serializeNarsilError, createVersionHandler, acceptorOf, createDocumentReadHandlers, sendError, respondError, respondJson, MAX_INDEX_TOUCH_INTERVAL_MS, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, clearGateSlot, parseJson, validateCreateIndex, rejectInvalid, validateBatch, serializeBatchResult, validateDocumentBody, validateSuggest, validateQuery, parseTaskListQuery, parseJsonOptional, validateRebalance, sendStream, SNAPSHOT_ARCHIVE_CONTENT_TYPE, DOCUMENT_EXPORT_CONTENT_TYPE, IMPORT_FLUSHES_IN_FLIGHT, badRequest, SERVER_CAPABILITIES, toHttpError, RELAY_STREAM_CHUNKS_IN_FLIGHT, MIN_UNBOUNDED_SERVER_LIMIT, MIN_COUNTED_SERVER_LIMIT } from './chunk-LPBWCHBE.mjs';
|
|
2
|
+
export { ASYNC_IMPORT_CAPABILITY, DOCUMENT_EXPORT_CAPABILITY, INDEX_LIFECYCLE_CAPABILITY, REBUILD_ANALYSIS_CAPABILITY, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, httpStatusForNarsilError } from './chunk-LPBWCHBE.mjs';
|
|
3
|
+
import { validateIndexName } from './chunk-2WLD2NFW.mjs';
|
|
4
|
+
import { engineCoreOf, providedDocId, resolveVectorText } from './chunk-AFKH4ZK3.mjs';
|
|
5
|
+
import { detectRuntime } from './chunk-4MQ5F4IL.mjs';
|
|
6
|
+
import './chunk-AK3BLGCI.mjs';
|
|
8
7
|
import './chunk-TGP5M5R7.mjs';
|
|
9
|
-
import './chunk-
|
|
8
|
+
import './chunk-PU43WDY4.mjs';
|
|
10
9
|
import './chunk-U2BKYEC7.mjs';
|
|
11
|
-
import './chunk-
|
|
10
|
+
import './chunk-LJYTW7GT.mjs';
|
|
12
11
|
import { startIdleHeapCleanup } from './chunk-Y3L5MDRV.mjs';
|
|
13
|
-
import { NarsilError, ErrorCodes, ServerErrorCodes, isNarsilError } from './chunk-
|
|
14
|
-
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, isNarsilError } from './chunk-
|
|
12
|
+
import { NarsilError, ErrorCodes, ServerErrorCodes, isNarsilError } from './chunk-I64LXKO3.mjs';
|
|
13
|
+
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, isNarsilError } from './chunk-I64LXKO3.mjs';
|
|
15
14
|
import { randomUUID } from 'crypto';
|
|
15
|
+
import { createReadStream } from 'fs';
|
|
16
|
+
import { rm } from 'fs/promises';
|
|
17
|
+
import path from 'path';
|
|
16
18
|
import { MessageChannel } from 'worker_threads';
|
|
17
19
|
|
|
18
|
-
// src/server/handlers/admin.ts
|
|
19
20
|
function createAdminHandlers(deps) {
|
|
20
21
|
const { engine, tasks, limits } = deps;
|
|
21
22
|
async function checkpoint(ctx) {
|
|
@@ -28,9 +29,12 @@ function createAdminHandlers(deps) {
|
|
|
28
29
|
}
|
|
29
30
|
async function snapshot(ctx) {
|
|
30
31
|
try {
|
|
31
|
-
const
|
|
32
|
-
if (ctx.abort.aborted)
|
|
33
|
-
|
|
32
|
+
const archive = await engine.snapshot(ctx.params[0]);
|
|
33
|
+
if (ctx.abort.aborted) {
|
|
34
|
+
await archive.cancel();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
await sendStream(ctx.res, ctx.abort, archive, [["Content-Type", SNAPSHOT_ARCHIVE_CONTENT_TYPE]]);
|
|
34
38
|
} catch (err) {
|
|
35
39
|
respondError(ctx, err);
|
|
36
40
|
}
|
|
@@ -118,15 +122,26 @@ function createAdminHandlers(deps) {
|
|
|
118
122
|
respondJson(ctx, record, 202);
|
|
119
123
|
}
|
|
120
124
|
async function restore(ctx) {
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
125
|
+
const spooled = ctx.spooledBody;
|
|
126
|
+
if (spooled === null || spooled.bytes === 0) {
|
|
127
|
+
await spooled?.remove();
|
|
123
128
|
sendError(ctx.res, 400, ServerErrorCodes.EMPTY_BODY, "Request body is empty");
|
|
124
129
|
return;
|
|
125
130
|
}
|
|
126
131
|
const name = ctx.params[0];
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
try {
|
|
133
|
+
const record = await tasks.start("restore", name, async () => {
|
|
134
|
+
try {
|
|
135
|
+
await engine.restore(name, createReadStream(spooled.path));
|
|
136
|
+
} finally {
|
|
137
|
+
await spooled.remove();
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
respondJson(ctx, record, 202);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
await spooled.remove();
|
|
143
|
+
respondError(ctx, err);
|
|
144
|
+
}
|
|
130
145
|
}
|
|
131
146
|
async function getTask(ctx) {
|
|
132
147
|
const record = await tasks.get(ctx.params[0]);
|
|
@@ -270,6 +285,54 @@ function createClusterHandlers(deps) {
|
|
|
270
285
|
}
|
|
271
286
|
return { topology, allocation };
|
|
272
287
|
}
|
|
288
|
+
function importResultOf(result, maxErrors) {
|
|
289
|
+
const errors = result.refused.slice(0, maxErrors);
|
|
290
|
+
return {
|
|
291
|
+
indexed: result.imported,
|
|
292
|
+
failed: result.refusedCount,
|
|
293
|
+
errors,
|
|
294
|
+
errorsTruncated: result.refusedCount > errors.length
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function createDocumentExportHandlers(deps) {
|
|
298
|
+
const { engine, tasks, limits } = deps;
|
|
299
|
+
async function exportDocuments(ctx) {
|
|
300
|
+
try {
|
|
301
|
+
const lines = await engine.exportDocuments(ctx.params[0]);
|
|
302
|
+
if (ctx.abort.aborted) {
|
|
303
|
+
await lines.cancel();
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
await sendStream(ctx.res, ctx.abort, lines, [["Content-Type", DOCUMENT_EXPORT_CONTENT_TYPE]]);
|
|
307
|
+
} catch (err) {
|
|
308
|
+
respondError(ctx, err);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async function importExport(ctx) {
|
|
312
|
+
const spooled = ctx.spooledBody;
|
|
313
|
+
if (spooled === null || spooled.bytes === 0) {
|
|
314
|
+
await spooled?.remove();
|
|
315
|
+
sendError(ctx.res, 400, ServerErrorCodes.EMPTY_BODY, "Request body is empty");
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const name = ctx.params[0];
|
|
319
|
+
try {
|
|
320
|
+
const record = await tasks.start("importExport", name, async (context) => {
|
|
321
|
+
try {
|
|
322
|
+
const result = await engine.importDocumentExport(name, createReadStream(spooled.path));
|
|
323
|
+
context.reportResult(importResultOf(result, limits.maxImportErrors));
|
|
324
|
+
} finally {
|
|
325
|
+
await spooled.remove();
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
respondJson(ctx, record, 202);
|
|
329
|
+
} catch (err) {
|
|
330
|
+
await spooled.remove();
|
|
331
|
+
respondError(ctx, err);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return { exportDocuments, importExport };
|
|
335
|
+
}
|
|
273
336
|
|
|
274
337
|
// src/server/handlers/documents.ts
|
|
275
338
|
function createDocumentHandlers(deps) {
|
|
@@ -757,6 +820,7 @@ var ENGINE_METHOD_SAMPLE = ["createIndex", "listIndexes", "insert", "query", "ge
|
|
|
757
820
|
var LIMITS_UNBOUNDED_AT_ZERO = [
|
|
758
821
|
"maxBodyBytes",
|
|
759
822
|
"maxImportBytes",
|
|
823
|
+
"maxRestoreBytes",
|
|
760
824
|
"maxLineBytes",
|
|
761
825
|
"maxImportErrors",
|
|
762
826
|
"maxConcurrentRequests",
|
|
@@ -808,10 +872,32 @@ function bodyBytes(body) {
|
|
|
808
872
|
if (typeof body === "string") return Buffer.from(body, "utf8");
|
|
809
873
|
return body;
|
|
810
874
|
}
|
|
811
|
-
function
|
|
875
|
+
function createRelayAbort() {
|
|
876
|
+
const listeners = [];
|
|
877
|
+
let aborted = false;
|
|
878
|
+
return {
|
|
879
|
+
get aborted() {
|
|
880
|
+
return aborted;
|
|
881
|
+
},
|
|
882
|
+
onAbort(fn) {
|
|
883
|
+
if (aborted) fn();
|
|
884
|
+
else listeners.push(fn);
|
|
885
|
+
},
|
|
886
|
+
trigger() {
|
|
887
|
+
if (aborted) return;
|
|
888
|
+
aborted = true;
|
|
889
|
+
for (const fn of listeners) fn();
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
function createCapturingResponse(remoteAddress, requestId, sendPart) {
|
|
812
894
|
let status = DEFAULT_STATUS;
|
|
813
895
|
const headers = [];
|
|
814
896
|
let finished = false;
|
|
897
|
+
let streaming = false;
|
|
898
|
+
let inFlight = 0;
|
|
899
|
+
let writable = null;
|
|
900
|
+
const abort = createRelayAbort();
|
|
815
901
|
let resolveDone = () => void 0;
|
|
816
902
|
const done = new Promise((resolve) => {
|
|
817
903
|
resolveDone = resolve;
|
|
@@ -819,25 +905,57 @@ function createCapturingResponse(remoteAddress) {
|
|
|
819
905
|
function finish(body) {
|
|
820
906
|
if (finished) return;
|
|
821
907
|
finished = true;
|
|
908
|
+
if (streaming) {
|
|
909
|
+
sendPart({ type: "stream-end", requestId, failed: false }, []);
|
|
910
|
+
resolveDone(null);
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
822
913
|
resolveDone({ status, headers, body });
|
|
823
914
|
}
|
|
915
|
+
function startStreaming() {
|
|
916
|
+
if (streaming) return;
|
|
917
|
+
streaming = true;
|
|
918
|
+
sendPart({ type: "stream-start", requestId, status, headers }, []);
|
|
919
|
+
}
|
|
824
920
|
const sink = {
|
|
825
921
|
cork(callback) {
|
|
826
922
|
callback();
|
|
827
923
|
return sink;
|
|
828
924
|
},
|
|
829
925
|
writeStatus(line) {
|
|
830
|
-
if (!finished) status = statusOf(line);
|
|
926
|
+
if (!finished && !streaming) status = statusOf(line);
|
|
831
927
|
return sink;
|
|
832
928
|
},
|
|
833
929
|
writeHeader(key, value) {
|
|
834
|
-
if (!finished) headers.push([key, value]);
|
|
930
|
+
if (!finished && !streaming) headers.push([key, value]);
|
|
835
931
|
return sink;
|
|
836
932
|
},
|
|
837
933
|
end(body) {
|
|
838
934
|
finish(bodyBytes(body));
|
|
839
935
|
return sink;
|
|
840
936
|
},
|
|
937
|
+
write(chunk) {
|
|
938
|
+
if (finished || abort.aborted) return true;
|
|
939
|
+
startStreaming();
|
|
940
|
+
const copy = chunk.slice();
|
|
941
|
+
inFlight += 1;
|
|
942
|
+
sendPart({ type: "stream-chunk", requestId, chunk: copy }, [copy.buffer]);
|
|
943
|
+
return inFlight < RELAY_STREAM_CHUNKS_IN_FLIGHT;
|
|
944
|
+
},
|
|
945
|
+
pause: () => void 0,
|
|
946
|
+
resume: () => void 0,
|
|
947
|
+
close() {
|
|
948
|
+
if (finished) return sink;
|
|
949
|
+
finished = true;
|
|
950
|
+
if (streaming) {
|
|
951
|
+
sendPart({ type: "stream-end", requestId, failed: true }, []);
|
|
952
|
+
resolveDone(null);
|
|
953
|
+
} else {
|
|
954
|
+
status = NO_RESPONSE_STATUS;
|
|
955
|
+
resolveDone({ status, headers, body: new Uint8Array(0) });
|
|
956
|
+
}
|
|
957
|
+
return sink;
|
|
958
|
+
},
|
|
841
959
|
endWithoutBody() {
|
|
842
960
|
finish(new Uint8Array(0));
|
|
843
961
|
return sink;
|
|
@@ -847,16 +965,45 @@ function createCapturingResponse(remoteAddress) {
|
|
|
847
965
|
return [true, true];
|
|
848
966
|
},
|
|
849
967
|
getWriteOffset: () => 0,
|
|
850
|
-
onWritable
|
|
968
|
+
onWritable(handler) {
|
|
969
|
+
writable = handler;
|
|
970
|
+
return sink;
|
|
971
|
+
},
|
|
851
972
|
onAborted: () => sink,
|
|
852
973
|
onData: () => sink,
|
|
853
974
|
getRemoteAddressAsText: () => new TextEncoder().encode(remoteAddress).buffer
|
|
854
975
|
};
|
|
855
976
|
return {
|
|
856
977
|
sink,
|
|
978
|
+
abort,
|
|
857
979
|
done,
|
|
980
|
+
credit() {
|
|
981
|
+
inFlight = Math.max(0, inFlight - 1);
|
|
982
|
+
if (inFlight >= RELAY_STREAM_CHUNKS_IN_FLIGHT || writable === null) return;
|
|
983
|
+
const handler = writable;
|
|
984
|
+
writable = null;
|
|
985
|
+
handler(0);
|
|
986
|
+
},
|
|
987
|
+
cancel() {
|
|
988
|
+
abort.trigger();
|
|
989
|
+
if (writable !== null) {
|
|
990
|
+
const handler = writable;
|
|
991
|
+
writable = null;
|
|
992
|
+
handler(0);
|
|
993
|
+
}
|
|
994
|
+
if (!finished) {
|
|
995
|
+
finished = true;
|
|
996
|
+
resolveDone(null);
|
|
997
|
+
}
|
|
998
|
+
},
|
|
858
999
|
finishUnanswered() {
|
|
859
1000
|
if (finished) return;
|
|
1001
|
+
if (streaming) {
|
|
1002
|
+
finished = true;
|
|
1003
|
+
sendPart({ type: "stream-end", requestId, failed: true }, []);
|
|
1004
|
+
resolveDone(null);
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
860
1007
|
status = NO_RESPONSE_STATUS;
|
|
861
1008
|
finish(new Uint8Array(0));
|
|
862
1009
|
}
|
|
@@ -867,22 +1014,36 @@ function toRelayedResponse(requestId, captured) {
|
|
|
867
1014
|
}
|
|
868
1015
|
|
|
869
1016
|
// src/server/request-threads/host.ts
|
|
870
|
-
var
|
|
1017
|
+
var RELAYED_TYPES = /* @__PURE__ */ new Set(["request", "authorize", "embed", "stream-credit", "stream-cancel"]);
|
|
871
1018
|
function isRelayRequest(message) {
|
|
872
1019
|
if (typeof message !== "object" || message === null) return false;
|
|
873
1020
|
const { type, requestId } = message;
|
|
874
1021
|
if (type === "touch") return true;
|
|
875
|
-
return typeof requestId === "number" &&
|
|
1022
|
+
return typeof requestId === "number" && typeof type === "string" && RELAYED_TYPES.has(type);
|
|
876
1023
|
}
|
|
877
|
-
|
|
878
|
-
|
|
1024
|
+
function spooledBodyOf(relayed) {
|
|
1025
|
+
if (relayed === null) return null;
|
|
1026
|
+
return {
|
|
1027
|
+
path: relayed.path,
|
|
1028
|
+
bytes: relayed.bytes,
|
|
1029
|
+
remove: () => rm(path.dirname(relayed.path), { recursive: true, force: true })
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
async function answerRequest(handlers, request, port, streams) {
|
|
1033
|
+
const captured = createCapturingResponse(
|
|
1034
|
+
request.hookContext?.remoteAddress ?? "",
|
|
1035
|
+
request.requestId,
|
|
1036
|
+
(part, moved) => port.postMessage(part, moved)
|
|
1037
|
+
);
|
|
1038
|
+
streams.set(request.requestId, captured);
|
|
879
1039
|
const ctx = {
|
|
880
1040
|
res: captured.sink,
|
|
881
1041
|
params: request.params,
|
|
882
1042
|
query: new URLSearchParams(request.query),
|
|
883
1043
|
contentType: request.contentType,
|
|
884
1044
|
rawBody: request.rawBody === null ? null : Buffer.from(request.rawBody.buffer, request.rawBody.byteOffset, request.rawBody.byteLength),
|
|
885
|
-
|
|
1045
|
+
spooledBody: spooledBodyOf(request.spooledBody),
|
|
1046
|
+
abort: captured.abort,
|
|
886
1047
|
hookContext: request.hookContext
|
|
887
1048
|
};
|
|
888
1049
|
try {
|
|
@@ -891,7 +1052,9 @@ async function answerRequest(handlers, request) {
|
|
|
891
1052
|
sendError(ctx.res, 500, ServerErrorCodes.INTERNAL_ERROR, "An unexpected error occurred");
|
|
892
1053
|
}
|
|
893
1054
|
captured.finishUnanswered();
|
|
894
|
-
|
|
1055
|
+
const answered = await captured.done;
|
|
1056
|
+
streams.delete(request.requestId);
|
|
1057
|
+
return answered === null ? null : toRelayedResponse(request.requestId, answered);
|
|
895
1058
|
}
|
|
896
1059
|
async function answerAuthorize(authorize, request) {
|
|
897
1060
|
if (authorize === void 0) {
|
|
@@ -942,14 +1105,25 @@ async function startRequestThreads(options) {
|
|
|
942
1105
|
const threads = /* @__PURE__ */ new Map();
|
|
943
1106
|
let stopped = false;
|
|
944
1107
|
function relayFrom(port) {
|
|
1108
|
+
const streams = /* @__PURE__ */ new Map();
|
|
945
1109
|
port.on("message", (message) => {
|
|
946
1110
|
if (!isRelayRequest(message)) return;
|
|
947
1111
|
if (message.type === "touch") {
|
|
948
1112
|
core.orchestrator.noteAccess(message.indexName);
|
|
949
1113
|
return;
|
|
950
1114
|
}
|
|
951
|
-
|
|
952
|
-
|
|
1115
|
+
if (message.type === "stream-credit") {
|
|
1116
|
+
streams.get(message.requestId)?.credit();
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
if (message.type === "stream-cancel") {
|
|
1120
|
+
streams.get(message.requestId)?.cancel();
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
const reply = message.type === "request" ? answerRequest(handlers, message, port, streams) : message.type === "authorize" ? answerAuthorize(authorize, message) : answerEmbed(core, message);
|
|
1124
|
+
void reply.then((answer) => {
|
|
1125
|
+
if (answer !== null) port.postMessage(answer);
|
|
1126
|
+
});
|
|
953
1127
|
});
|
|
954
1128
|
}
|
|
955
1129
|
async function stopThread(workerId, thread) {
|
|
@@ -982,7 +1156,8 @@ async function startRequestThreads(options) {
|
|
|
982
1156
|
limits: options.limits,
|
|
983
1157
|
build: options.build,
|
|
984
1158
|
authorizes: authorize !== void 0,
|
|
985
|
-
searchHooks
|
|
1159
|
+
searchHooks,
|
|
1160
|
+
patternWorkCap: options.core.patternWorkCap
|
|
986
1161
|
}
|
|
987
1162
|
},
|
|
988
1163
|
[channel.port1]
|
|
@@ -1253,6 +1428,7 @@ function resolveLimits(limits) {
|
|
|
1253
1428
|
return {
|
|
1254
1429
|
maxBodyBytes: limits?.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,
|
|
1255
1430
|
maxImportBytes: limits?.maxImportBytes ?? DEFAULT_MAX_IMPORT_BYTES,
|
|
1431
|
+
maxRestoreBytes: limits?.maxRestoreBytes ?? DEFAULT_MAX_RESTORE_BYTES,
|
|
1256
1432
|
maxLineBytes: limits?.maxLineBytes ?? DEFAULT_MAX_LINE_BYTES,
|
|
1257
1433
|
importBatchSize: limits?.importBatchSize ?? DEFAULT_IMPORT_BATCH_SIZE,
|
|
1258
1434
|
maxConcurrentRequests: limits?.maxConcurrentRequests ?? DEFAULT_MAX_CONCURRENT_REQUESTS,
|
|
@@ -1286,6 +1462,7 @@ function mainThreadHandlers(deps) {
|
|
|
1286
1462
|
const doc = createDocumentHandlers(deps);
|
|
1287
1463
|
const search = createSearchHandlers(deps);
|
|
1288
1464
|
const admin = createAdminHandlers(deps);
|
|
1465
|
+
const documentExport = createDocumentExportHandlers(deps);
|
|
1289
1466
|
const health = createHealthHandlers(deps);
|
|
1290
1467
|
const cluster = createClusterHandlers(deps);
|
|
1291
1468
|
const version = createVersionHandler(deps);
|
|
@@ -1332,7 +1509,9 @@ function mainThreadHandlers(deps) {
|
|
|
1332
1509
|
optimize: admin.optimize,
|
|
1333
1510
|
rebalance: admin.rebalance,
|
|
1334
1511
|
partitionConfig: admin.partitionConfig,
|
|
1335
|
-
restore: admin.restore
|
|
1512
|
+
restore: admin.restore,
|
|
1513
|
+
exportDocuments: documentExport.exportDocuments,
|
|
1514
|
+
importExport: documentExport.importExport
|
|
1336
1515
|
};
|
|
1337
1516
|
}
|
|
1338
1517
|
var NarsilHttpServer = class {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MemoryStats } from './memory-
|
|
1
|
+
import { M as MemoryStats } from './memory-B4jMmygw.js';
|
|
2
2
|
|
|
3
3
|
/** Declarative index configuration accepted over HTTP. Function-valued engine
|
|
4
4
|
* options (custom tokenizer, stopWords-as-function, group reducer, embedding
|
|
@@ -142,7 +142,7 @@ interface MemoryStatsResponse extends MemoryStats {
|
|
|
142
142
|
*
|
|
143
143
|
* @public
|
|
144
144
|
*/
|
|
145
|
-
type TaskType = 'optimizeVectors' | 'rebalance' | 'restore' | 'import' | 'rebuildAnalysis';
|
|
145
|
+
type TaskType = 'optimizeVectors' | 'rebalance' | 'restore' | 'import' | 'importExport' | 'rebuildAnalysis';
|
|
146
146
|
/**
|
|
147
147
|
* Where a long-running operation stands.
|
|
148
148
|
*
|
|
@@ -207,7 +207,7 @@ interface TaskRecord {
|
|
|
207
207
|
cancelRequestedAt?: number;
|
|
208
208
|
/** How far the work has gone, which an import reports and other task types omit. */
|
|
209
209
|
progress?: TaskProgress;
|
|
210
|
-
/** What the work produced, which an import reports once it finishes. */
|
|
210
|
+
/** What the work produced, which an `import` or `importExport` task reports once it finishes. */
|
|
211
211
|
result?: ImportResult;
|
|
212
212
|
/** This says why the task failed, and a failed task alone carries it. */
|
|
213
213
|
error?: {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { loadUWebSockets, childAppOf, createRouteRunner, corsHeaderReader, createSharedRequestGate, registerServerRoutes, sendRelayed, createDocumentReadHandlers, respondJson, SERVER_CAPABILITIES, versionReport, sendError, serverRoutes, parseJson, validateSuggest, rejectInvalid, respondError, validateQuery } from './chunk-
|
|
2
|
-
import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import {
|
|
5
|
-
import { extractVectorFieldsFromSchema } from './chunk-653BNMAF.mjs';
|
|
1
|
+
import { loadUWebSockets, childAppOf, createRouteRunner, corsHeaderReader, createSharedRequestGate, registerServerRoutes, sendRelayed, createDocumentReadHandlers, respondJson, SERVER_CAPABILITIES, versionReport, statusLine, sendError, serverRoutes, parseJson, validateSuggest, rejectInvalid, respondError, validateQuery } from './chunk-LPBWCHBE.mjs';
|
|
2
|
+
import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-ZULSEZCE.mjs';
|
|
3
|
+
import { resolveProjection, projectionKeepsField, setNestedValue } from './chunk-3YKWSO54.mjs';
|
|
4
|
+
import { extractVectorFieldsFromSchema } from './chunk-AK3BLGCI.mjs';
|
|
6
5
|
import './chunk-ZJ4CSAB2.mjs';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import
|
|
6
|
+
import './chunk-PU43WDY4.mjs';
|
|
7
|
+
import './chunk-ZKRV5M2P.mjs';
|
|
8
|
+
import './chunk-LJYTW7GT.mjs';
|
|
9
|
+
import { ServerErrorCodes, NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
|
|
10
10
|
|
|
11
11
|
// src/server/request-threads/held-vectors.ts
|
|
12
12
|
function managerWithHeldVectors(manager, fieldPaths, vectorOf) {
|
|
@@ -28,7 +28,7 @@ function managerWithHeldVectors(manager, fieldPaths, vectorOf) {
|
|
|
28
28
|
|
|
29
29
|
// src/server/request-threads/read-engine.ts
|
|
30
30
|
function createThreadReadEngine(options) {
|
|
31
|
-
const { executor, relay, searchHooks } = options;
|
|
31
|
+
const { executor, relay, searchHooks, patternWorkCap } = options;
|
|
32
32
|
function vectorFieldsOf(context) {
|
|
33
33
|
return [...extractVectorFieldsFromSchema(context.config.schema).keys()];
|
|
34
34
|
}
|
|
@@ -110,7 +110,8 @@ function createThreadReadEngine(options) {
|
|
|
110
110
|
config: context.config,
|
|
111
111
|
indexName,
|
|
112
112
|
cursorBinding: queryBindingOf(params),
|
|
113
|
-
vectorSearchers: context.vectorSearchers
|
|
113
|
+
vectorSearchers: context.vectorSearchers,
|
|
114
|
+
patternWorkCap
|
|
114
115
|
});
|
|
115
116
|
if (context.analysisStale) result.analysisStale = true;
|
|
116
117
|
return result;
|
|
@@ -123,7 +124,8 @@ function createThreadReadEngine(options) {
|
|
|
123
124
|
config: context.config,
|
|
124
125
|
indexName,
|
|
125
126
|
cursorBinding: queryBindingOf(params),
|
|
126
|
-
vectorSearchers: context.vectorSearchers
|
|
127
|
+
vectorSearchers: context.vectorSearchers,
|
|
128
|
+
patternWorkCap
|
|
127
129
|
});
|
|
128
130
|
if (context.analysisStale) result.analysisStale = true;
|
|
129
131
|
return result;
|
|
@@ -157,7 +159,8 @@ function createThreadReadEngine(options) {
|
|
|
157
159
|
return executeListDocuments(params ?? {}, {
|
|
158
160
|
manager,
|
|
159
161
|
schema: context.config.schema,
|
|
160
|
-
strict: context.config.strict
|
|
162
|
+
strict: context.config.strict,
|
|
163
|
+
patternWorkCap
|
|
161
164
|
});
|
|
162
165
|
}
|
|
163
166
|
};
|
|
@@ -169,6 +172,46 @@ function isRelayReply(message) {
|
|
|
169
172
|
const { type, requestId } = message;
|
|
170
173
|
return typeof requestId === "number" && (type === "response" || type === "authorized" || type === "embedded");
|
|
171
174
|
}
|
|
175
|
+
function isStreamPart(message) {
|
|
176
|
+
if (typeof message !== "object" || message === null) return false;
|
|
177
|
+
const { type, requestId } = message;
|
|
178
|
+
return typeof requestId === "number" && (type === "stream-start" || type === "stream-chunk" || type === "stream-end");
|
|
179
|
+
}
|
|
180
|
+
function writeStreamPart(port, writer, part) {
|
|
181
|
+
const { ctx } = writer;
|
|
182
|
+
if (part.type === "stream-end") {
|
|
183
|
+
if (!ctx.abort.aborted) {
|
|
184
|
+
ctx.res.cork(() => {
|
|
185
|
+
if (part.failed) ctx.res.close();
|
|
186
|
+
else ctx.res.end();
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
writer.finish();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (ctx.abort.aborted) return;
|
|
193
|
+
if (part.type === "stream-start") {
|
|
194
|
+
writer.started = true;
|
|
195
|
+
ctx.res.cork(() => {
|
|
196
|
+
ctx.res.writeStatus(statusLine(part.status));
|
|
197
|
+
for (const [key, value] of part.headers) ctx.res.writeHeader(key, value);
|
|
198
|
+
});
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
let writable = true;
|
|
202
|
+
ctx.res.cork(() => {
|
|
203
|
+
writable = ctx.res.write(part.chunk);
|
|
204
|
+
});
|
|
205
|
+
const credit = () => port.postMessage({ type: "stream-credit", requestId: part.requestId });
|
|
206
|
+
if (writable) {
|
|
207
|
+
credit();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
ctx.res.onWritable(() => {
|
|
211
|
+
credit();
|
|
212
|
+
return true;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
172
215
|
function errorOf(reply) {
|
|
173
216
|
const error = reply.error ?? { code: ErrorCodes.EMBEDDING_FAILED, message: "The main thread returned no vector" };
|
|
174
217
|
return new NarsilError(error.code, error.message, error.details);
|
|
@@ -201,11 +244,18 @@ function createRelayClient(port, touchIntervalMs) {
|
|
|
201
244
|
pending.clear();
|
|
202
245
|
for (const entry of waiting) entry.reject(portClosedError());
|
|
203
246
|
}
|
|
247
|
+
const writers = /* @__PURE__ */ new Map();
|
|
204
248
|
port.on("message", (message) => {
|
|
249
|
+
if (isStreamPart(message)) {
|
|
250
|
+
const writer = writers.get(message.requestId);
|
|
251
|
+
if (writer !== void 0) writeStreamPart(port, writer, message);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
205
254
|
if (!isRelayReply(message)) return;
|
|
206
255
|
const waiting = pending.get(message.requestId);
|
|
207
256
|
if (waiting === void 0) return;
|
|
208
257
|
pending.delete(message.requestId);
|
|
258
|
+
writers.delete(message.requestId);
|
|
209
259
|
waiting.resolve(message);
|
|
210
260
|
});
|
|
211
261
|
port.on("close", failAll);
|
|
@@ -240,24 +290,36 @@ function createRelayClient(port, touchIntervalMs) {
|
|
|
240
290
|
let reply;
|
|
241
291
|
const body = relayedBody(ctx.rawBody);
|
|
242
292
|
try {
|
|
243
|
-
reply = await
|
|
244
|
-
(requestId) =>
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
293
|
+
reply = await new Promise((resolve, reject) => {
|
|
294
|
+
void send((requestId) => {
|
|
295
|
+
writers.set(requestId, {
|
|
296
|
+
ctx,
|
|
297
|
+
started: false,
|
|
298
|
+
finish: () => {
|
|
299
|
+
writers.delete(requestId);
|
|
300
|
+
pending.delete(requestId);
|
|
301
|
+
resolve(null);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
ctx.abort.onAbort(() => port.postMessage({ type: "stream-cancel", requestId }));
|
|
305
|
+
return {
|
|
306
|
+
type: "request",
|
|
307
|
+
requestId,
|
|
308
|
+
route,
|
|
309
|
+
params: ctx.params,
|
|
310
|
+
query: ctx.query.toString(),
|
|
311
|
+
contentType: ctx.contentType,
|
|
312
|
+
rawBody: body.bytes,
|
|
313
|
+
spooledBody: ctx.spooledBody === null ? null : { path: ctx.spooledBody.path, bytes: ctx.spooledBody.bytes },
|
|
314
|
+
hookContext: ctx.hookContext
|
|
315
|
+
};
|
|
316
|
+
}, body.moved).then(resolve, reject);
|
|
317
|
+
});
|
|
256
318
|
} catch {
|
|
257
319
|
if (!ctx.abort.aborted) sendUnavailable(ctx.res);
|
|
258
320
|
return;
|
|
259
321
|
}
|
|
260
|
-
if (reply.type !== "response" || ctx.abort.aborted) return;
|
|
322
|
+
if (reply === null || reply.type !== "response" || ctx.abort.aborted) return;
|
|
261
323
|
sendRelayed(ctx.res, ctx.abort, reply.status, reply.headers, reply.body);
|
|
262
324
|
},
|
|
263
325
|
async embed(indexName, vector) {
|
|
@@ -381,7 +443,12 @@ async function serveRequests(executor, settings) {
|
|
|
381
443
|
const child = childAppOf(app);
|
|
382
444
|
if (child === null) throw new Error("This uWebSockets.js build offers no child apps");
|
|
383
445
|
const relay = createRelayClient(settings.port, settings.touchIntervalMs);
|
|
384
|
-
const local = createThreadReadEngine({
|
|
446
|
+
const local = createThreadReadEngine({
|
|
447
|
+
executor,
|
|
448
|
+
relay,
|
|
449
|
+
searchHooks: settings.searchHooks,
|
|
450
|
+
patternWorkCap: settings.patternWorkCap
|
|
451
|
+
});
|
|
385
452
|
const run = createRouteRunner({
|
|
386
453
|
authorize: settings.authorizes ? (context) => relay.authorize(context) : void 0,
|
|
387
454
|
gate: createSharedRequestGate(settings.gate, settings.maxConcurrentRequests, settings.gateSlot),
|
|
@@ -31,7 +31,7 @@ interface TransportConfig {
|
|
|
31
31
|
requestTimeout: number;
|
|
32
32
|
/** A replication entry may take this long to reach a replica and come back acknowledged. */
|
|
33
33
|
replicationTimeout: number;
|
|
34
|
-
/** A
|
|
34
|
+
/** A node waits this long for each next chunk of a snapshot transfer, which moves a partition or an index between nodes, so that the node can receive a transfer of any size while the sender keeps sending. */
|
|
35
35
|
snapshotTimeout: number;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { openSharedVectorField, MAX_WORKER_COPIES, createVectorStore, osqBitsOf, createHNSWIndex, createOsqQuantizer, osqRecordBytes } from '../chunk-
|
|
1
|
+
import { openSharedVectorField, MAX_WORKER_COPIES, createVectorStore, osqBitsOf, createHNSWIndex, createOsqQuantizer, osqRecordBytes } from '../chunk-WVDFG45M.mjs';
|
|
2
2
|
import '../chunk-ZJ4CSAB2.mjs';
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-PU43WDY4.mjs';
|
|
4
|
+
import '../chunk-LJYTW7GT.mjs';
|
|
5
|
+
import '../chunk-I64LXKO3.mjs';
|
|
6
6
|
|
|
7
7
|
// src/vector/worker-copy.ts
|
|
8
8
|
function restoreQuantizer(snapshot, store) {
|