@delali/narsil 0.3.1-next.72 → 0.3.1-next.74
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-D6gjjQyA.d.ts → capabilities-CAMzmkAg.d.ts} +19 -4
- package/dist/{chunk-P2ZZN32C.mjs → chunk-2E35UM3G.mjs} +2 -12
- package/dist/chunk-3DDUNI6N.mjs +48 -0
- package/dist/{chunk-KZTI25D3.mjs → chunk-4MQ5F4IL.mjs} +1 -1
- package/dist/{chunk-HVJYTKK7.mjs → chunk-BVBIQQKG.mjs} +947 -1327
- package/dist/{chunk-2X2ZQOAB.mjs → chunk-CTOSGRM7.mjs} +101 -21
- package/dist/{chunk-7QMTA7AA.mjs → chunk-CUZOX6CN.mjs} +7784 -4276
- package/dist/chunk-I23G3IZC.mjs +593 -0
- package/dist/{chunk-RV77FR2F.mjs → chunk-I64LXKO3.mjs} +0 -1
- package/dist/chunk-KEHK2O6P.mjs +13 -0
- package/dist/{chunk-CVPA5Q7R.mjs → chunk-LX4JERXI.mjs} +9 -6
- package/dist/{chunk-EDMCZLSJ.mjs → chunk-NOZUQM7J.mjs} +193 -13
- package/dist/{chunk-LCCL6EEH.mjs → chunk-PO53FV4Q.mjs} +93 -94
- package/dist/chunk-T5ZWEWVD.mjs +658 -0
- package/dist/{chunk-Y52WZWAU.mjs → chunk-TVFLHM7M.mjs} +4 -4
- package/dist/{chunk-QR4OKRVY.mjs → chunk-VKX2BPXD.mjs} +147 -642
- package/dist/{chunk-3HQPUCCT.mjs → chunk-XW25X6AU.mjs} +66 -237
- package/dist/{chunk-M6XF5HDE.mjs → chunk-Z3DQPOJQ.mjs} +127 -30
- package/dist/{client-C2TiW29y.d.ts → client-C-I70ArH.d.ts} +77 -26
- package/dist/client.d.ts +9 -9
- package/dist/client.mjs +44 -22
- package/dist/{config-BLguB-om.d.ts → config-C6Iw5rCX.d.ts} +11 -4
- package/dist/{config-C7Ip8Ife.d.ts → config-DJPH3IQB.d.ts} +11 -2
- package/dist/direct-executor-KFAGILJC.mjs +17 -0
- package/dist/distribution/coordinator/etcd.d.ts +29 -16
- package/dist/distribution/coordinator/etcd.mjs +162 -75
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- 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 +647 -366
- package/dist/embeddings/openai.mjs +1 -1
- package/dist/{engine-Dm4446j1.d.ts → engine-B8eRPO7m.d.ts} +97 -188
- package/dist/index.browser.mjs +12132 -8592
- package/dist/index.d.ts +27 -8
- package/dist/index.mjs +15 -14
- package/dist/{memory-CKHTU1CL.d.ts → memory-DJEwWoCi.d.ts} +1204 -968
- package/dist/partial-words-DTIHO8G4.d.ts +19 -0
- package/dist/partial-words.d.ts +22 -0
- package/dist/partial-words.mjs +11 -0
- package/dist/pattern.mjs +1 -1
- package/dist/persistence/durability/checkpoint-worker.d.ts +57 -29
- package/dist/persistence/durability/checkpoint-worker.mjs +26 -16
- package/dist/react.d.ts +7 -7
- package/dist/react.mjs +0 -1
- package/dist/{schema-BBOCdhND.d.ts → schema-DgyDijhf.d.ts} +6 -2
- package/dist/server.d.ts +11 -11
- package/dist/server.mjs +212 -32
- package/dist/{tasks-BECd0b__.d.ts → tasks-BVmAKYBh.d.ts} +3 -3
- package/dist/{thread-IBSIZZ6W.mjs → thread-W6DPKEF6.mjs} +82 -21
- package/dist/{types-BQDlIvfS.d.ts → types-B3b68nfF.d.ts} +1 -1
- package/dist/{types-D5OwhtsQ.d.ts → types-Cb9kiY5P.d.ts} +1 -1
- package/dist/{types-BiUmaiWT.d.ts → types-ChrVy4lH.d.ts} +1 -1
- package/dist/vector/search-worker.d.ts +1 -1
- package/dist/vector/search-worker.mjs +4 -3
- package/dist/workers/entry.mjs +4 -4
- package/package.json +15 -7
- package/dist/chunk-3L4U6EJQ.mjs +0 -49
- package/dist/chunk-IFBKLBGB.mjs +0 -7
- package/dist/chunk-XZ4PAREY.mjs +0 -25
- package/dist/direct-executor-SVCHXR74.mjs +0 -14
- 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,24 @@
|
|
|
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 './chunk-
|
|
6
|
-
import
|
|
7
|
-
import './chunk-M6XF5HDE.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-NOZUQM7J.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-NOZUQM7J.mjs';
|
|
3
|
+
import { validateIndexName } from './chunk-TVFLHM7M.mjs';
|
|
4
|
+
import { engineCoreOf, providedDocId, resolveVectorText } from './chunk-LX4JERXI.mjs';
|
|
5
|
+
import { detectRuntime } from './chunk-4MQ5F4IL.mjs';
|
|
6
|
+
import './chunk-3DDUNI6N.mjs';
|
|
8
7
|
import './chunk-TGP5M5R7.mjs';
|
|
9
|
-
import './chunk-
|
|
8
|
+
import './chunk-2E35UM3G.mjs';
|
|
9
|
+
import './chunk-Z3DQPOJQ.mjs';
|
|
10
|
+
import './chunk-KEHK2O6P.mjs';
|
|
10
11
|
import './chunk-U2BKYEC7.mjs';
|
|
11
12
|
import './chunk-LJYTW7GT.mjs';
|
|
12
13
|
import { startIdleHeapCleanup } from './chunk-Y3L5MDRV.mjs';
|
|
13
|
-
import { NarsilError, ErrorCodes, ServerErrorCodes, isNarsilError } from './chunk-
|
|
14
|
-
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, isNarsilError } from './chunk-
|
|
14
|
+
import { NarsilError, ErrorCodes, ServerErrorCodes, isNarsilError } from './chunk-I64LXKO3.mjs';
|
|
15
|
+
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, isNarsilError } from './chunk-I64LXKO3.mjs';
|
|
15
16
|
import { randomUUID } from 'crypto';
|
|
17
|
+
import { createReadStream } from 'fs';
|
|
18
|
+
import { rm } from 'fs/promises';
|
|
19
|
+
import path from 'path';
|
|
16
20
|
import { MessageChannel } from 'worker_threads';
|
|
17
21
|
|
|
18
|
-
// src/server/handlers/admin.ts
|
|
19
22
|
function createAdminHandlers(deps) {
|
|
20
23
|
const { engine, tasks, limits } = deps;
|
|
21
24
|
async function checkpoint(ctx) {
|
|
@@ -28,9 +31,12 @@ function createAdminHandlers(deps) {
|
|
|
28
31
|
}
|
|
29
32
|
async function snapshot(ctx) {
|
|
30
33
|
try {
|
|
31
|
-
const
|
|
32
|
-
if (ctx.abort.aborted)
|
|
33
|
-
|
|
34
|
+
const archive = await engine.snapshot(ctx.params[0]);
|
|
35
|
+
if (ctx.abort.aborted) {
|
|
36
|
+
await archive.cancel();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await sendStream(ctx.res, ctx.abort, archive, [["Content-Type", SNAPSHOT_ARCHIVE_CONTENT_TYPE]]);
|
|
34
40
|
} catch (err) {
|
|
35
41
|
respondError(ctx, err);
|
|
36
42
|
}
|
|
@@ -118,15 +124,26 @@ function createAdminHandlers(deps) {
|
|
|
118
124
|
respondJson(ctx, record, 202);
|
|
119
125
|
}
|
|
120
126
|
async function restore(ctx) {
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
127
|
+
const spooled = ctx.spooledBody;
|
|
128
|
+
if (spooled === null || spooled.bytes === 0) {
|
|
129
|
+
await spooled?.remove();
|
|
123
130
|
sendError(ctx.res, 400, ServerErrorCodes.EMPTY_BODY, "Request body is empty");
|
|
124
131
|
return;
|
|
125
132
|
}
|
|
126
133
|
const name = ctx.params[0];
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
134
|
+
try {
|
|
135
|
+
const record = await tasks.start("restore", name, async () => {
|
|
136
|
+
try {
|
|
137
|
+
await engine.restore(name, createReadStream(spooled.path));
|
|
138
|
+
} finally {
|
|
139
|
+
await spooled.remove();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
respondJson(ctx, record, 202);
|
|
143
|
+
} catch (err) {
|
|
144
|
+
await spooled.remove();
|
|
145
|
+
respondError(ctx, err);
|
|
146
|
+
}
|
|
130
147
|
}
|
|
131
148
|
async function getTask(ctx) {
|
|
132
149
|
const record = await tasks.get(ctx.params[0]);
|
|
@@ -270,6 +287,54 @@ function createClusterHandlers(deps) {
|
|
|
270
287
|
}
|
|
271
288
|
return { topology, allocation };
|
|
272
289
|
}
|
|
290
|
+
function importResultOf(result, maxErrors) {
|
|
291
|
+
const errors = result.refused.slice(0, maxErrors);
|
|
292
|
+
return {
|
|
293
|
+
indexed: result.imported,
|
|
294
|
+
failed: result.refusedCount,
|
|
295
|
+
errors,
|
|
296
|
+
errorsTruncated: result.refusedCount > errors.length
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function createDocumentExportHandlers(deps) {
|
|
300
|
+
const { engine, tasks, limits } = deps;
|
|
301
|
+
async function exportDocuments(ctx) {
|
|
302
|
+
try {
|
|
303
|
+
const lines = await engine.exportDocuments(ctx.params[0]);
|
|
304
|
+
if (ctx.abort.aborted) {
|
|
305
|
+
await lines.cancel();
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
await sendStream(ctx.res, ctx.abort, lines, [["Content-Type", DOCUMENT_EXPORT_CONTENT_TYPE]]);
|
|
309
|
+
} catch (err) {
|
|
310
|
+
respondError(ctx, err);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async function importExport(ctx) {
|
|
314
|
+
const spooled = ctx.spooledBody;
|
|
315
|
+
if (spooled === null || spooled.bytes === 0) {
|
|
316
|
+
await spooled?.remove();
|
|
317
|
+
sendError(ctx.res, 400, ServerErrorCodes.EMPTY_BODY, "Request body is empty");
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const name = ctx.params[0];
|
|
321
|
+
try {
|
|
322
|
+
const record = await tasks.start("importExport", name, async (context) => {
|
|
323
|
+
try {
|
|
324
|
+
const result = await engine.importDocumentExport(name, createReadStream(spooled.path));
|
|
325
|
+
context.reportResult(importResultOf(result, limits.maxImportErrors));
|
|
326
|
+
} finally {
|
|
327
|
+
await spooled.remove();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
respondJson(ctx, record, 202);
|
|
331
|
+
} catch (err) {
|
|
332
|
+
await spooled.remove();
|
|
333
|
+
respondError(ctx, err);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return { exportDocuments, importExport };
|
|
337
|
+
}
|
|
273
338
|
|
|
274
339
|
// src/server/handlers/documents.ts
|
|
275
340
|
function createDocumentHandlers(deps) {
|
|
@@ -757,6 +822,7 @@ var ENGINE_METHOD_SAMPLE = ["createIndex", "listIndexes", "insert", "query", "ge
|
|
|
757
822
|
var LIMITS_UNBOUNDED_AT_ZERO = [
|
|
758
823
|
"maxBodyBytes",
|
|
759
824
|
"maxImportBytes",
|
|
825
|
+
"maxRestoreBytes",
|
|
760
826
|
"maxLineBytes",
|
|
761
827
|
"maxImportErrors",
|
|
762
828
|
"maxConcurrentRequests",
|
|
@@ -808,10 +874,32 @@ function bodyBytes(body) {
|
|
|
808
874
|
if (typeof body === "string") return Buffer.from(body, "utf8");
|
|
809
875
|
return body;
|
|
810
876
|
}
|
|
811
|
-
function
|
|
877
|
+
function createRelayAbort() {
|
|
878
|
+
const listeners = [];
|
|
879
|
+
let aborted = false;
|
|
880
|
+
return {
|
|
881
|
+
get aborted() {
|
|
882
|
+
return aborted;
|
|
883
|
+
},
|
|
884
|
+
onAbort(fn) {
|
|
885
|
+
if (aborted) fn();
|
|
886
|
+
else listeners.push(fn);
|
|
887
|
+
},
|
|
888
|
+
trigger() {
|
|
889
|
+
if (aborted) return;
|
|
890
|
+
aborted = true;
|
|
891
|
+
for (const fn of listeners) fn();
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
function createCapturingResponse(remoteAddress, requestId, sendPart) {
|
|
812
896
|
let status = DEFAULT_STATUS;
|
|
813
897
|
const headers = [];
|
|
814
898
|
let finished = false;
|
|
899
|
+
let streaming = false;
|
|
900
|
+
let inFlight = 0;
|
|
901
|
+
let writable = null;
|
|
902
|
+
const abort = createRelayAbort();
|
|
815
903
|
let resolveDone = () => void 0;
|
|
816
904
|
const done = new Promise((resolve) => {
|
|
817
905
|
resolveDone = resolve;
|
|
@@ -819,25 +907,57 @@ function createCapturingResponse(remoteAddress) {
|
|
|
819
907
|
function finish(body) {
|
|
820
908
|
if (finished) return;
|
|
821
909
|
finished = true;
|
|
910
|
+
if (streaming) {
|
|
911
|
+
sendPart({ type: "stream-end", requestId, failed: false }, []);
|
|
912
|
+
resolveDone(null);
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
822
915
|
resolveDone({ status, headers, body });
|
|
823
916
|
}
|
|
917
|
+
function startStreaming() {
|
|
918
|
+
if (streaming) return;
|
|
919
|
+
streaming = true;
|
|
920
|
+
sendPart({ type: "stream-start", requestId, status, headers }, []);
|
|
921
|
+
}
|
|
824
922
|
const sink = {
|
|
825
923
|
cork(callback) {
|
|
826
924
|
callback();
|
|
827
925
|
return sink;
|
|
828
926
|
},
|
|
829
927
|
writeStatus(line) {
|
|
830
|
-
if (!finished) status = statusOf(line);
|
|
928
|
+
if (!finished && !streaming) status = statusOf(line);
|
|
831
929
|
return sink;
|
|
832
930
|
},
|
|
833
931
|
writeHeader(key, value) {
|
|
834
|
-
if (!finished) headers.push([key, value]);
|
|
932
|
+
if (!finished && !streaming) headers.push([key, value]);
|
|
835
933
|
return sink;
|
|
836
934
|
},
|
|
837
935
|
end(body) {
|
|
838
936
|
finish(bodyBytes(body));
|
|
839
937
|
return sink;
|
|
840
938
|
},
|
|
939
|
+
write(chunk) {
|
|
940
|
+
if (finished || abort.aborted) return true;
|
|
941
|
+
startStreaming();
|
|
942
|
+
const copy = chunk.slice();
|
|
943
|
+
inFlight += 1;
|
|
944
|
+
sendPart({ type: "stream-chunk", requestId, chunk: copy }, [copy.buffer]);
|
|
945
|
+
return inFlight < RELAY_STREAM_CHUNKS_IN_FLIGHT;
|
|
946
|
+
},
|
|
947
|
+
pause: () => void 0,
|
|
948
|
+
resume: () => void 0,
|
|
949
|
+
close() {
|
|
950
|
+
if (finished) return sink;
|
|
951
|
+
finished = true;
|
|
952
|
+
if (streaming) {
|
|
953
|
+
sendPart({ type: "stream-end", requestId, failed: true }, []);
|
|
954
|
+
resolveDone(null);
|
|
955
|
+
} else {
|
|
956
|
+
status = NO_RESPONSE_STATUS;
|
|
957
|
+
resolveDone({ status, headers, body: new Uint8Array(0) });
|
|
958
|
+
}
|
|
959
|
+
return sink;
|
|
960
|
+
},
|
|
841
961
|
endWithoutBody() {
|
|
842
962
|
finish(new Uint8Array(0));
|
|
843
963
|
return sink;
|
|
@@ -847,16 +967,45 @@ function createCapturingResponse(remoteAddress) {
|
|
|
847
967
|
return [true, true];
|
|
848
968
|
},
|
|
849
969
|
getWriteOffset: () => 0,
|
|
850
|
-
onWritable
|
|
970
|
+
onWritable(handler) {
|
|
971
|
+
writable = handler;
|
|
972
|
+
return sink;
|
|
973
|
+
},
|
|
851
974
|
onAborted: () => sink,
|
|
852
975
|
onData: () => sink,
|
|
853
976
|
getRemoteAddressAsText: () => new TextEncoder().encode(remoteAddress).buffer
|
|
854
977
|
};
|
|
855
978
|
return {
|
|
856
979
|
sink,
|
|
980
|
+
abort,
|
|
857
981
|
done,
|
|
982
|
+
credit() {
|
|
983
|
+
inFlight = Math.max(0, inFlight - 1);
|
|
984
|
+
if (inFlight >= RELAY_STREAM_CHUNKS_IN_FLIGHT || writable === null) return;
|
|
985
|
+
const handler = writable;
|
|
986
|
+
writable = null;
|
|
987
|
+
handler(0);
|
|
988
|
+
},
|
|
989
|
+
cancel() {
|
|
990
|
+
abort.trigger();
|
|
991
|
+
if (writable !== null) {
|
|
992
|
+
const handler = writable;
|
|
993
|
+
writable = null;
|
|
994
|
+
handler(0);
|
|
995
|
+
}
|
|
996
|
+
if (!finished) {
|
|
997
|
+
finished = true;
|
|
998
|
+
resolveDone(null);
|
|
999
|
+
}
|
|
1000
|
+
},
|
|
858
1001
|
finishUnanswered() {
|
|
859
1002
|
if (finished) return;
|
|
1003
|
+
if (streaming) {
|
|
1004
|
+
finished = true;
|
|
1005
|
+
sendPart({ type: "stream-end", requestId, failed: true }, []);
|
|
1006
|
+
resolveDone(null);
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
860
1009
|
status = NO_RESPONSE_STATUS;
|
|
861
1010
|
finish(new Uint8Array(0));
|
|
862
1011
|
}
|
|
@@ -867,22 +1016,36 @@ function toRelayedResponse(requestId, captured) {
|
|
|
867
1016
|
}
|
|
868
1017
|
|
|
869
1018
|
// src/server/request-threads/host.ts
|
|
870
|
-
var
|
|
1019
|
+
var RELAYED_TYPES = /* @__PURE__ */ new Set(["request", "authorize", "embed", "stream-credit", "stream-cancel"]);
|
|
871
1020
|
function isRelayRequest(message) {
|
|
872
1021
|
if (typeof message !== "object" || message === null) return false;
|
|
873
1022
|
const { type, requestId } = message;
|
|
874
1023
|
if (type === "touch") return true;
|
|
875
|
-
return typeof requestId === "number" &&
|
|
1024
|
+
return typeof requestId === "number" && typeof type === "string" && RELAYED_TYPES.has(type);
|
|
876
1025
|
}
|
|
877
|
-
|
|
878
|
-
|
|
1026
|
+
function spooledBodyOf(relayed) {
|
|
1027
|
+
if (relayed === null) return null;
|
|
1028
|
+
return {
|
|
1029
|
+
path: relayed.path,
|
|
1030
|
+
bytes: relayed.bytes,
|
|
1031
|
+
remove: () => rm(path.dirname(relayed.path), { recursive: true, force: true })
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
async function answerRequest(handlers, request, port, streams) {
|
|
1035
|
+
const captured = createCapturingResponse(
|
|
1036
|
+
request.hookContext?.remoteAddress ?? "",
|
|
1037
|
+
request.requestId,
|
|
1038
|
+
(part, moved) => port.postMessage(part, moved)
|
|
1039
|
+
);
|
|
1040
|
+
streams.set(request.requestId, captured);
|
|
879
1041
|
const ctx = {
|
|
880
1042
|
res: captured.sink,
|
|
881
1043
|
params: request.params,
|
|
882
1044
|
query: new URLSearchParams(request.query),
|
|
883
1045
|
contentType: request.contentType,
|
|
884
1046
|
rawBody: request.rawBody === null ? null : Buffer.from(request.rawBody.buffer, request.rawBody.byteOffset, request.rawBody.byteLength),
|
|
885
|
-
|
|
1047
|
+
spooledBody: spooledBodyOf(request.spooledBody),
|
|
1048
|
+
abort: captured.abort,
|
|
886
1049
|
hookContext: request.hookContext
|
|
887
1050
|
};
|
|
888
1051
|
try {
|
|
@@ -891,7 +1054,9 @@ async function answerRequest(handlers, request) {
|
|
|
891
1054
|
sendError(ctx.res, 500, ServerErrorCodes.INTERNAL_ERROR, "An unexpected error occurred");
|
|
892
1055
|
}
|
|
893
1056
|
captured.finishUnanswered();
|
|
894
|
-
|
|
1057
|
+
const answered = await captured.done;
|
|
1058
|
+
streams.delete(request.requestId);
|
|
1059
|
+
return answered === null ? null : toRelayedResponse(request.requestId, answered);
|
|
895
1060
|
}
|
|
896
1061
|
async function answerAuthorize(authorize, request) {
|
|
897
1062
|
if (authorize === void 0) {
|
|
@@ -942,14 +1107,25 @@ async function startRequestThreads(options) {
|
|
|
942
1107
|
const threads = /* @__PURE__ */ new Map();
|
|
943
1108
|
let stopped = false;
|
|
944
1109
|
function relayFrom(port) {
|
|
1110
|
+
const streams = /* @__PURE__ */ new Map();
|
|
945
1111
|
port.on("message", (message) => {
|
|
946
1112
|
if (!isRelayRequest(message)) return;
|
|
947
1113
|
if (message.type === "touch") {
|
|
948
1114
|
core.orchestrator.noteAccess(message.indexName);
|
|
949
1115
|
return;
|
|
950
1116
|
}
|
|
951
|
-
|
|
952
|
-
|
|
1117
|
+
if (message.type === "stream-credit") {
|
|
1118
|
+
streams.get(message.requestId)?.credit();
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
if (message.type === "stream-cancel") {
|
|
1122
|
+
streams.get(message.requestId)?.cancel();
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
const reply = message.type === "request" ? answerRequest(handlers, message, port, streams) : message.type === "authorize" ? answerAuthorize(authorize, message) : answerEmbed(core, message);
|
|
1126
|
+
void reply.then((answer) => {
|
|
1127
|
+
if (answer !== null) port.postMessage(answer);
|
|
1128
|
+
});
|
|
953
1129
|
});
|
|
954
1130
|
}
|
|
955
1131
|
async function stopThread(workerId, thread) {
|
|
@@ -1254,6 +1430,7 @@ function resolveLimits(limits) {
|
|
|
1254
1430
|
return {
|
|
1255
1431
|
maxBodyBytes: limits?.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,
|
|
1256
1432
|
maxImportBytes: limits?.maxImportBytes ?? DEFAULT_MAX_IMPORT_BYTES,
|
|
1433
|
+
maxRestoreBytes: limits?.maxRestoreBytes ?? DEFAULT_MAX_RESTORE_BYTES,
|
|
1257
1434
|
maxLineBytes: limits?.maxLineBytes ?? DEFAULT_MAX_LINE_BYTES,
|
|
1258
1435
|
importBatchSize: limits?.importBatchSize ?? DEFAULT_IMPORT_BATCH_SIZE,
|
|
1259
1436
|
maxConcurrentRequests: limits?.maxConcurrentRequests ?? DEFAULT_MAX_CONCURRENT_REQUESTS,
|
|
@@ -1287,6 +1464,7 @@ function mainThreadHandlers(deps) {
|
|
|
1287
1464
|
const doc = createDocumentHandlers(deps);
|
|
1288
1465
|
const search = createSearchHandlers(deps);
|
|
1289
1466
|
const admin = createAdminHandlers(deps);
|
|
1467
|
+
const documentExport = createDocumentExportHandlers(deps);
|
|
1290
1468
|
const health = createHealthHandlers(deps);
|
|
1291
1469
|
const cluster = createClusterHandlers(deps);
|
|
1292
1470
|
const version = createVersionHandler(deps);
|
|
@@ -1333,7 +1511,9 @@ function mainThreadHandlers(deps) {
|
|
|
1333
1511
|
optimize: admin.optimize,
|
|
1334
1512
|
rebalance: admin.rebalance,
|
|
1335
1513
|
partitionConfig: admin.partitionConfig,
|
|
1336
|
-
restore: admin.restore
|
|
1514
|
+
restore: admin.restore,
|
|
1515
|
+
exportDocuments: documentExport.exportDocuments,
|
|
1516
|
+
importExport: documentExport.importExport
|
|
1337
1517
|
};
|
|
1338
1518
|
}
|
|
1339
1519
|
var NarsilHttpServer = class {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MemoryStats } from './memory-
|
|
1
|
+
import { M as MemoryStats } from './memory-DJEwWoCi.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,13 +1,15 @@
|
|
|
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-M6XF5HDE.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-NOZUQM7J.mjs';
|
|
2
|
+
import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-CTOSGRM7.mjs';
|
|
3
|
+
import { resolveProjection, projectionKeepsField, setNestedValue } from './chunk-VKX2BPXD.mjs';
|
|
4
|
+
import './chunk-3DDUNI6N.mjs';
|
|
6
5
|
import './chunk-ZJ4CSAB2.mjs';
|
|
7
|
-
import './chunk-
|
|
6
|
+
import './chunk-2E35UM3G.mjs';
|
|
8
7
|
import './chunk-ZKRV5M2P.mjs';
|
|
8
|
+
import './chunk-I23G3IZC.mjs';
|
|
9
|
+
import { extractVectorFieldsFromSchema } from './chunk-Z3DQPOJQ.mjs';
|
|
10
|
+
import './chunk-KEHK2O6P.mjs';
|
|
9
11
|
import './chunk-LJYTW7GT.mjs';
|
|
10
|
-
import { ServerErrorCodes, NarsilError, ErrorCodes } from './chunk-
|
|
12
|
+
import { ServerErrorCodes, NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
|
|
11
13
|
|
|
12
14
|
// src/server/request-threads/held-vectors.ts
|
|
13
15
|
function managerWithHeldVectors(manager, fieldPaths, vectorOf) {
|
|
@@ -173,6 +175,46 @@ function isRelayReply(message) {
|
|
|
173
175
|
const { type, requestId } = message;
|
|
174
176
|
return typeof requestId === "number" && (type === "response" || type === "authorized" || type === "embedded");
|
|
175
177
|
}
|
|
178
|
+
function isStreamPart(message) {
|
|
179
|
+
if (typeof message !== "object" || message === null) return false;
|
|
180
|
+
const { type, requestId } = message;
|
|
181
|
+
return typeof requestId === "number" && (type === "stream-start" || type === "stream-chunk" || type === "stream-end");
|
|
182
|
+
}
|
|
183
|
+
function writeStreamPart(port, writer, part) {
|
|
184
|
+
const { ctx } = writer;
|
|
185
|
+
if (part.type === "stream-end") {
|
|
186
|
+
if (!ctx.abort.aborted) {
|
|
187
|
+
ctx.res.cork(() => {
|
|
188
|
+
if (part.failed) ctx.res.close();
|
|
189
|
+
else ctx.res.end();
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
writer.finish();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (ctx.abort.aborted) return;
|
|
196
|
+
if (part.type === "stream-start") {
|
|
197
|
+
writer.started = true;
|
|
198
|
+
ctx.res.cork(() => {
|
|
199
|
+
ctx.res.writeStatus(statusLine(part.status));
|
|
200
|
+
for (const [key, value] of part.headers) ctx.res.writeHeader(key, value);
|
|
201
|
+
});
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
let writable = true;
|
|
205
|
+
ctx.res.cork(() => {
|
|
206
|
+
writable = ctx.res.write(part.chunk);
|
|
207
|
+
});
|
|
208
|
+
const credit = () => port.postMessage({ type: "stream-credit", requestId: part.requestId });
|
|
209
|
+
if (writable) {
|
|
210
|
+
credit();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
ctx.res.onWritable(() => {
|
|
214
|
+
credit();
|
|
215
|
+
return true;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
176
218
|
function errorOf(reply) {
|
|
177
219
|
const error = reply.error ?? { code: ErrorCodes.EMBEDDING_FAILED, message: "The main thread returned no vector" };
|
|
178
220
|
return new NarsilError(error.code, error.message, error.details);
|
|
@@ -205,11 +247,18 @@ function createRelayClient(port, touchIntervalMs) {
|
|
|
205
247
|
pending.clear();
|
|
206
248
|
for (const entry of waiting) entry.reject(portClosedError());
|
|
207
249
|
}
|
|
250
|
+
const writers = /* @__PURE__ */ new Map();
|
|
208
251
|
port.on("message", (message) => {
|
|
252
|
+
if (isStreamPart(message)) {
|
|
253
|
+
const writer = writers.get(message.requestId);
|
|
254
|
+
if (writer !== void 0) writeStreamPart(port, writer, message);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
209
257
|
if (!isRelayReply(message)) return;
|
|
210
258
|
const waiting = pending.get(message.requestId);
|
|
211
259
|
if (waiting === void 0) return;
|
|
212
260
|
pending.delete(message.requestId);
|
|
261
|
+
writers.delete(message.requestId);
|
|
213
262
|
waiting.resolve(message);
|
|
214
263
|
});
|
|
215
264
|
port.on("close", failAll);
|
|
@@ -244,24 +293,36 @@ function createRelayClient(port, touchIntervalMs) {
|
|
|
244
293
|
let reply;
|
|
245
294
|
const body = relayedBody(ctx.rawBody);
|
|
246
295
|
try {
|
|
247
|
-
reply = await
|
|
248
|
-
(requestId) =>
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
296
|
+
reply = await new Promise((resolve, reject) => {
|
|
297
|
+
void send((requestId) => {
|
|
298
|
+
writers.set(requestId, {
|
|
299
|
+
ctx,
|
|
300
|
+
started: false,
|
|
301
|
+
finish: () => {
|
|
302
|
+
writers.delete(requestId);
|
|
303
|
+
pending.delete(requestId);
|
|
304
|
+
resolve(null);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
ctx.abort.onAbort(() => port.postMessage({ type: "stream-cancel", requestId }));
|
|
308
|
+
return {
|
|
309
|
+
type: "request",
|
|
310
|
+
requestId,
|
|
311
|
+
route,
|
|
312
|
+
params: ctx.params,
|
|
313
|
+
query: ctx.query.toString(),
|
|
314
|
+
contentType: ctx.contentType,
|
|
315
|
+
rawBody: body.bytes,
|
|
316
|
+
spooledBody: ctx.spooledBody === null ? null : { path: ctx.spooledBody.path, bytes: ctx.spooledBody.bytes },
|
|
317
|
+
hookContext: ctx.hookContext
|
|
318
|
+
};
|
|
319
|
+
}, body.moved).then(resolve, reject);
|
|
320
|
+
});
|
|
260
321
|
} catch {
|
|
261
322
|
if (!ctx.abort.aborted) sendUnavailable(ctx.res);
|
|
262
323
|
return;
|
|
263
324
|
}
|
|
264
|
-
if (reply.type !== "response" || ctx.abort.aborted) return;
|
|
325
|
+
if (reply === null || reply.type !== "response" || ctx.abort.aborted) return;
|
|
265
326
|
sendRelayed(ctx.res, ctx.abort, reply.status, reply.headers, reply.body);
|
|
266
327
|
},
|
|
267
328
|
async embed(indexName, vector) {
|
|
@@ -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,9 @@
|
|
|
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-PO53FV4Q.mjs';
|
|
2
2
|
import '../chunk-ZJ4CSAB2.mjs';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-2E35UM3G.mjs';
|
|
4
|
+
import '../chunk-KEHK2O6P.mjs';
|
|
4
5
|
import '../chunk-LJYTW7GT.mjs';
|
|
5
|
-
import '../chunk-
|
|
6
|
+
import '../chunk-I64LXKO3.mjs';
|
|
6
7
|
|
|
7
8
|
// src/vector/worker-copy.ts
|
|
8
9
|
function restoreQuantizer(snapshot, store) {
|
package/dist/workers/entry.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { startIdleHeapCleanup } from '../chunk-Y3L5MDRV.mjs';
|
|
2
2
|
import { threadSlotOfWorker, isValidWorkerAction } from '../chunk-POWOTUKJ.mjs';
|
|
3
|
-
import { ErrorCodes, NarsilError, isNarsilError } from '../chunk-
|
|
3
|
+
import { ErrorCodes, NarsilError, isNarsilError } from '../chunk-I64LXKO3.mjs';
|
|
4
4
|
|
|
5
5
|
// src/workers/action-handler.ts
|
|
6
6
|
function buildErrorResponse(requestId, code, message, details) {
|
|
@@ -18,7 +18,7 @@ async function importBootstrapModule(moduleUrl) {
|
|
|
18
18
|
await import(moduleUrl);
|
|
19
19
|
}
|
|
20
20
|
async function stopServingRequests() {
|
|
21
|
-
const { closeRequestThread } = await import('../thread-
|
|
21
|
+
const { closeRequestThread } = await import('../thread-W6DPKEF6.mjs');
|
|
22
22
|
closeRequestThread();
|
|
23
23
|
}
|
|
24
24
|
function holdsCopies(executor) {
|
|
@@ -49,7 +49,7 @@ function createActionHandler(executor) {
|
|
|
49
49
|
if (!holdsCopies(executor)) {
|
|
50
50
|
throw new NarsilError(ErrorCodes.CONFIG_INVALID, "This executor holds no copies to answer requests from");
|
|
51
51
|
}
|
|
52
|
-
const starting = import('../thread-
|
|
52
|
+
const starting = import('../thread-W6DPKEF6.mjs').then(
|
|
53
53
|
({ serveRequests }) => serveRequests(executor, action.settings)
|
|
54
54
|
);
|
|
55
55
|
serving.start = starting.then(
|
|
@@ -102,7 +102,7 @@ async function setup() {
|
|
|
102
102
|
} catch {
|
|
103
103
|
parentPort = null;
|
|
104
104
|
}
|
|
105
|
-
const { createDirectExecutor } = await import('../direct-executor-
|
|
105
|
+
const { createDirectExecutor } = await import('../direct-executor-KFAGILJC.mjs');
|
|
106
106
|
const handleAction = createActionHandler(createDirectExecutor({ threadSlot }));
|
|
107
107
|
if (parentPort) {
|
|
108
108
|
const port = parentPort;
|