@delali/narsil 0.2.4-next.52 → 0.2.4-next.54
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 +8 -4
- package/dist/adapters/filesystem.mjs +1 -1
- package/dist/adapters/indexeddb.mjs +1 -1
- package/dist/{capabilities-CuTSXvbN.d.ts → capabilities-DlYw0Ov0.d.ts} +13 -2
- package/dist/{chunk-U36IDJN7.mjs → chunk-4NVPQ6S5.mjs} +2 -2
- package/dist/{chunk-WM7IS45M.mjs → chunk-5T6AOR37.mjs} +2 -2
- package/dist/{chunk-ULJ36FK4.mjs → chunk-BH5SYB5W.mjs} +73 -46
- package/dist/{chunk-3GWP2TO6.mjs → chunk-D2S642IV.mjs} +4 -2
- package/dist/{chunk-P4ELXVJQ.mjs → chunk-FRQVMFY7.mjs} +7 -1
- package/dist/{chunk-ZT5BRDFW.mjs → chunk-L225SHNB.mjs} +2 -2
- package/dist/{chunk-72AXTIBW.mjs → chunk-NTZYA3SJ.mjs} +3 -3
- package/dist/{chunk-EY2ULUMT.mjs → chunk-RGS7FMCB.mjs} +25 -5
- package/dist/{chunk-YPYULM5E.mjs → chunk-TVT5V4E7.mjs} +84 -33
- package/dist/{chunk-T62YOSGS.mjs → chunk-U2AL3SON.mjs} +16 -98
- package/dist/chunk-UTOFOJOR.mjs +135 -0
- package/dist/{chunk-2FO7KZ6K.mjs → chunk-XNQAIO74.mjs} +53 -8
- package/dist/{client-BMJWVxOP.d.ts → client-CQUqt9Ir.d.ts} +13 -4
- package/dist/client.d.ts +8 -8
- package/dist/client.mjs +20 -14
- package/dist/{config-qMLpi5T4.d.ts → config-CNas6wJH.d.ts} +2 -2
- package/dist/{config-BcYZkdMw.d.ts → config-bXxnJrQc.d.ts} +80 -35
- package/dist/direct-executor-RBA5O7EN.mjs +12 -0
- package/dist/distribution/coordinator/etcd.d.ts +2 -2
- package/dist/distribution/coordinator/etcd.mjs +1 -1
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- package/dist/distribution/transport/grpc.mjs +1 -1
- package/dist/distribution.d.ts +8 -8
- package/dist/distribution.mjs +12 -12
- package/dist/embeddings/openai.mjs +1 -1
- package/dist/{engine-zhms1qId.d.ts → engine-Dj4I91Jv.d.ts} +21 -8
- package/dist/index.browser.mjs +169 -72
- package/dist/index.d.ts +7 -7
- package/dist/index.mjs +10 -10
- package/dist/{memory-OmgkX_Z2.d.ts → memory-xrXOZMbw.d.ts} +58 -13
- package/dist/persistence/durability/checkpoint-worker.d.ts +1 -1
- package/dist/persistence/durability/checkpoint-worker.mjs +10 -10
- package/dist/react.d.ts +11 -11
- package/dist/react.mjs +16 -4
- package/dist/{schema-OSWaaZzx.d.ts → schema-mLpXZBEh.d.ts} +13 -6
- package/dist/server.d.ts +13 -10
- package/dist/server.mjs +68 -20
- package/dist/{tasks-DiF1c9v2.d.ts → tasks-Df73Tjgq.d.ts} +9 -5
- package/dist/{thread-TLCX43WV.mjs → thread-5UP6MGED.mjs} +8 -8
- package/dist/{types-LEzMyjVX.d.ts → types-BTIVO8DI.d.ts} +1 -1
- package/dist/vector/search-worker.d.ts +1 -1
- package/dist/vector/search-worker.mjs +3 -3
- package/dist/workers/entry.mjs +23 -10
- package/package.json +7 -7
- package/dist/chunk-WFKIGEBY.mjs +0 -11
- package/dist/direct-executor-UJC36S2D.mjs +0 -12
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
# Narsil
|
|
4
4
|
|
|
@@ -8,11 +8,15 @@
|
|
|
8
8
|
[](https://www.npmjs.com/package/@delali/narsil)
|
|
9
9
|
[](https://github.com/assetcorp/narsil/blob/main/LICENSE)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The search engine that scales with your data.
|
|
12
12
|
|
|
13
|
-
Narsil is
|
|
13
|
+
Narsil is an open source search engine with full-text, vector, hybrid, and geosearch on one typed index. You can embed Narsil in your application process, where the engine searches without a network hop, or deploy it as a standalone search server with a REST API, a write-ahead log, and bulk NDJSON ingest. Both forms contain the same engine, which stores indexes in one cross-language binary format (`.nrsl`), so you can load an index from one form into the other.
|
|
14
14
|
|
|
15
|
-
The engine partitions large indexes across workers and merges the results of the partitions into a single ranked list.
|
|
15
|
+
The engine partitions large indexes across workers and merges the results of the partitions into a single ranked list. This TypeScript package is the reference implementation of the `.nrsl` format, so a second implementation in Go or Rust is the headline item on the [roadmap](https://github.com/assetcorp/narsil/blob/main/ROADMAP.md).
|
|
16
|
+
|
|
17
|
+
<!-- BENCH:headline START -->
|
|
18
|
+
On BEIR SciFact, Narsil's BM25 ranking scores 0.681 nDCG@10, which is within 0.002 of the Anserini reference of 0.679. Elasticsearch scores 0.679 and OpenSearch scores 0.679 on the same queries. On SciFact, Narsil answers 958 keyword queries a second at its peak, and OpenSearch follows with 878. On SciFact with every engine held at 0.99 recall, Narsil answers 259 vector queries a second at its peak, while OpenSearch leads with 730. Narsil has the highest peak throughput in 2 of the 6 keyword, vector, and hybrid comparisons in the newest recorded run, so read each figure beside its table. The harness recorded these figures in run `20260804T184221Z` on 2026-08-04, on GCP c3-standard-8, us-central1-a. You'll find every dataset, every engine's settings, and the full method in [`BENCHMARKS.md`](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md).
|
|
19
|
+
<!-- BENCH:headline END -->
|
|
16
20
|
|
|
17
21
|
Try it in your browser at [narsil.sondelali.com/demo](https://narsil.sondelali.com/demo). Read the full documentation at [narsil.sondelali.com/docs](https://narsil.sondelali.com/docs).
|
|
18
22
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { E as EmbeddingAdapter } from './adapters-79OIa4xm.js';
|
|
2
|
-
import { C as ClusterNamespace } from './config-
|
|
3
|
-
import { h as TaskStore } from './tasks-
|
|
2
|
+
import { C as ClusterNamespace } from './config-CNas6wJH.js';
|
|
3
|
+
import { h as TaskStore } from './tasks-Df73Tjgq.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Context handed to {@link OnRequestHook} for every inbound request, captured
|
|
@@ -181,6 +181,17 @@ interface NarsilServer {
|
|
|
181
181
|
listen(): Promise<void>;
|
|
182
182
|
/** Closes the socket and ends the server. The engine keeps running. */
|
|
183
183
|
close(): Promise<void>;
|
|
184
|
+
/**
|
|
185
|
+
* Closes the server and then shuts the engine down, which is what a process
|
|
186
|
+
* whose work is this server calls on its way out.
|
|
187
|
+
*
|
|
188
|
+
* Shutting the engine down is what ends the request threads, so Node aborts
|
|
189
|
+
* a process that exits while one of those threads still holds a client
|
|
190
|
+
* connection. Call {@link NarsilServer.close} on its own where the engine
|
|
191
|
+
* keeps running after the server closes, as in a process that fronts one
|
|
192
|
+
* engine with two servers.
|
|
193
|
+
*/
|
|
194
|
+
shutdown(): Promise<void>;
|
|
184
195
|
/** The server bound to this port, which is what you read after binding to port 0. */
|
|
185
196
|
readonly listeningPort: number;
|
|
186
197
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { validateRequiredFields } from './chunk-
|
|
2
|
-
import { ErrorCodes, NarsilError } from './chunk-
|
|
1
|
+
import { validateRequiredFields } from './chunk-L225SHNB.mjs';
|
|
2
|
+
import { ErrorCodes, NarsilError } from './chunk-FRQVMFY7.mjs';
|
|
3
3
|
|
|
4
4
|
// src/narsil/internals.ts
|
|
5
5
|
var engineCores = /* @__PURE__ */ new WeakMap();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { flattenSchema, SORTABLE_TEXT_FIELD_TYPE, MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, RESULT_WINDOW, DEFAULT_PAGE_SIZE, PROTOTYPE_POLLUTION_KEYS, isTextFieldType, PREFIX_MAX_EXPANSIONS, MAX_CURSOR_ANCHOR_CODE_POINTS } from './chunk-
|
|
1
|
+
import { flattenSchema, SORTABLE_TEXT_FIELD_TYPE, MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, RESULT_WINDOW, DEFAULT_PAGE_SIZE, PROTOTYPE_POLLUTION_KEYS, isTextFieldType, PREFIX_MAX_EXPANSIONS, MAX_CURSOR_ANCHOR_CODE_POINTS } from './chunk-L225SHNB.mjs';
|
|
2
2
|
import { compareCodePoints, compareComparableKeys, toComparableSortValue, readSortField, SORT_VALUE_MAX_CODE_POINTS, compareSortValues } from './chunk-2GWVQWGA.mjs';
|
|
3
|
-
import { createNarsilError, ErrorCodes, NarsilError } from './chunk-
|
|
3
|
+
import { createNarsilError, ErrorCodes, NarsilError } from './chunk-FRQVMFY7.mjs';
|
|
4
4
|
|
|
5
5
|
// src/core/tokenizer/constants.ts
|
|
6
6
|
var TOKEN_CACHE_SIZE_FLOOR = 5e4;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ReplicationMessageTypes } from './chunk-GCM3JFVA.mjs';
|
|
2
|
-
import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, admitInsert, asBatchInsertError, embedDocumentFields, assertDocumentCarriesMappedVectors } from './chunk-
|
|
3
|
-
import { getNestedValue, generateId, getLanguage, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, createCompositePartition, deserializePayloadV2, createSharedFrozenSegment, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, readHeapStatistics, resolveIndexAnalysis, deserializePayloadV1, decodeVectorIndexParts, resolveRequestThreadCount, createPartitionIndex, VECTOR_FILE_MAX_VECTORS, deadBytesFor, mergeFrozenSegments, isCompositePartition, workerResourceLimits, deserializeMetadata, isNodeMainThread, spawnNodeWorker, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, serializeMetadata, SHUTDOWN_TIMEOUT_MS, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, decodeVectorFilePayload, documentsOfPayloadV2, countDead, decodeVectorGraphPayload, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createFrozenSegment } from './chunk-
|
|
2
|
+
import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, admitInsert, asBatchInsertError, embedDocumentFields, assertDocumentCarriesMappedVectors } from './chunk-4NVPQ6S5.mjs';
|
|
3
|
+
import { getNestedValue, generateId, getLanguage, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, createCompositePartition, deserializePayloadV2, createSharedFrozenSegment, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, readHeapStatistics, resolveIndexAnalysis, deserializePayloadV1, decodeVectorIndexParts, resolveRequestThreadCount, createPartitionIndex, VECTOR_FILE_MAX_VECTORS, deadBytesFor, mergeFrozenSegments, isCompositePartition, workerResourceLimits, deserializeMetadata, isNodeMainThread, spawnNodeWorker, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, serializeMetadata, SHUTDOWN_TIMEOUT_MS, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, decodeVectorFilePayload, documentsOfPayloadV2, countDead, decodeVectorGraphPayload, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createFrozenSegment } from './chunk-XNQAIO74.mjs';
|
|
4
4
|
import { detectRuntime } from './chunk-AV4IJKD2.mjs';
|
|
5
|
-
import { validateWorkerConfig, validateIndexName, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-
|
|
6
|
-
import { BATCH_CHUNK_SIZE, STATISTICS_BROADCAST_INTERVAL_MS, MAX_SWEEP_INTERVAL_MS, MIN_SWEEP_INTERVAL_MS, HEAP_PRESSURE_WARNING_FRACTION, FOREIGN_STATS_TTL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, HEAP_PRESSURE_REARM_FRACTION } from './chunk-
|
|
7
|
-
import { collectQueryTermStats, mergePartitionStats, fnv1a, kWayMerge, mergeFacets } from './chunk-
|
|
8
|
-
import { extractVectorFieldsFromSchema, validateSchema, validateVectorPromotion, validateVectorStorage, flattenSchema, isTextFieldType, validateRequiredFields, validateDocument, validateDocumentStrict } from './chunk-
|
|
9
|
-
import { releaseLocksHeldBy } from './chunk-
|
|
5
|
+
import { validateWorkerConfig, validateIndexName, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-TVT5V4E7.mjs';
|
|
6
|
+
import { BATCH_CHUNK_SIZE, STATISTICS_BROADCAST_INTERVAL_MS, MAX_SWEEP_INTERVAL_MS, MIN_SWEEP_INTERVAL_MS, HEAP_PRESSURE_WARNING_FRACTION, FOREIGN_STATS_TTL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, HEAP_PRESSURE_REARM_FRACTION } from './chunk-D2S642IV.mjs';
|
|
7
|
+
import { collectQueryTermStats, mergePartitionStats, fnv1a, kWayMerge, mergeFacets } from './chunk-5T6AOR37.mjs';
|
|
8
|
+
import { extractVectorFieldsFromSchema, validateSchema, validateVectorPromotion, validateVectorStorage, flattenSchema, isTextFieldType, validateRequiredFields, validateDocument, validateDocumentStrict } from './chunk-L225SHNB.mjs';
|
|
9
|
+
import { releaseLocksHeldBy } from './chunk-U2AL3SON.mjs';
|
|
10
10
|
import { crc32, nativeCrc32, crc32Final, crc32Init, crc32Update } from './chunk-3L4U6EJQ.mjs';
|
|
11
11
|
import { CHECKSUM_TIMEOUT_MS, CHECKSUM_YIELD_CHUNK_BYTES } from './chunk-IFBKLBGB.mjs';
|
|
12
12
|
import { compareCodePoints } from './chunk-2GWVQWGA.mjs';
|
|
13
13
|
import { createRequestId, isValidWorkerResponse, threadSlotOfWorker } from './chunk-POWOTUKJ.mjs';
|
|
14
|
-
import { NarsilError, ErrorCodes } from './chunk-
|
|
14
|
+
import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
|
|
15
15
|
import { encode, decode } from '@msgpack/msgpack';
|
|
16
16
|
|
|
17
17
|
// src/partitioning/constants.ts
|
|
@@ -1083,7 +1083,7 @@ async function unpackEnvelope(data, maxAcceptedVersion = CURRENT_ENVELOPE_VERSIO
|
|
|
1083
1083
|
if (header.envelopeFormatVersion > maxAcceptedVersion) {
|
|
1084
1084
|
throw new NarsilError(
|
|
1085
1085
|
ErrorCodes.ENVELOPE_VERSION_MISMATCH,
|
|
1086
|
-
`This data
|
|
1086
|
+
`This data holds Narsil envelope format v${header.envelopeFormatVersion}, while this build of @delali/narsil reads up to v${maxAcceptedVersion}, so upgrade the package to read it.`
|
|
1087
1087
|
);
|
|
1088
1088
|
}
|
|
1089
1089
|
if (header.flags.encryptionEnabled) {
|
|
@@ -3824,6 +3824,8 @@ async function spawnWorker2() {
|
|
|
3824
3824
|
if (typeof worker.unref === "function") {
|
|
3825
3825
|
worker.unref();
|
|
3826
3826
|
}
|
|
3827
|
+
worker.on("error", () => discardWorker(worker));
|
|
3828
|
+
worker.on("exit", () => discardWorker(worker));
|
|
3827
3829
|
spawnedWorkerCount += 1;
|
|
3828
3830
|
return worker;
|
|
3829
3831
|
} catch {
|
|
@@ -6008,12 +6010,20 @@ function createInvalidationIntegration(deps) {
|
|
|
6008
6010
|
}
|
|
6009
6011
|
|
|
6010
6012
|
// src/engine/heap-pressure.ts
|
|
6013
|
+
function spentHeapFraction(heap) {
|
|
6014
|
+
if (heap.configuredLimitBytes !== null) return heap.usedBytes / heap.configuredLimitBytes;
|
|
6015
|
+
if (heap.availableBytes === null) return heap.usedBytes / heap.limitBytes;
|
|
6016
|
+
return 1 - heap.availableBytes / heap.limitBytes;
|
|
6017
|
+
}
|
|
6018
|
+
function ceilingBytes(heap) {
|
|
6019
|
+
return heap.configuredLimitBytes ?? heap.limitBytes;
|
|
6020
|
+
}
|
|
6011
6021
|
function createHeapPressureNotifier(deps) {
|
|
6012
6022
|
let warned = false;
|
|
6013
6023
|
function check(indexName) {
|
|
6014
6024
|
const heap = deps.readHeap();
|
|
6015
6025
|
if (heap === null) return;
|
|
6016
|
-
const fraction = heap
|
|
6026
|
+
const fraction = spentHeapFraction(heap);
|
|
6017
6027
|
if (warned) {
|
|
6018
6028
|
if (fraction < HEAP_PRESSURE_REARM_FRACTION) warned = false;
|
|
6019
6029
|
return;
|
|
@@ -6023,7 +6033,7 @@ function createHeapPressureNotifier(deps) {
|
|
|
6023
6033
|
deps.emit({
|
|
6024
6034
|
indexName,
|
|
6025
6035
|
heapUsed: heap.usedBytes,
|
|
6026
|
-
heapLimit: heap
|
|
6036
|
+
heapLimit: ceilingBytes(heap),
|
|
6027
6037
|
estimatedMemoryBytes: deps.estimateIndexBytes(indexName)
|
|
6028
6038
|
});
|
|
6029
6039
|
}
|
|
@@ -6751,7 +6761,7 @@ function createWorkerExecutor(worker, config) {
|
|
|
6751
6761
|
clearTimeout(entry.timeoutId);
|
|
6752
6762
|
pending.delete(response.requestId);
|
|
6753
6763
|
if (response.type === "error") {
|
|
6754
|
-
entry.reject(new NarsilError(response.code, response.message));
|
|
6764
|
+
entry.reject(new NarsilError(response.code, response.message, response.details));
|
|
6755
6765
|
} else {
|
|
6756
6766
|
entry.resolve(response.data);
|
|
6757
6767
|
}
|
|
@@ -7312,6 +7322,7 @@ function scheduleRequestThreadPoolRestart(state) {
|
|
|
7312
7322
|
if (typeof timer.unref === "function") timer.unref();
|
|
7313
7323
|
}
|
|
7314
7324
|
async function serveRequestsOnWorkers(state, listener) {
|
|
7325
|
+
if (!state.workersEnabled) return 0;
|
|
7315
7326
|
state.requestThreads = listener;
|
|
7316
7327
|
state.keywordWorkerCount = resolveRequestThreadCount(state.config?.workers?.count);
|
|
7317
7328
|
if (state.vectorCopyPolicy !== void 0) {
|
|
@@ -7334,6 +7345,7 @@ async function serveRequestsOnWorkers(state, listener) {
|
|
|
7334
7345
|
return pool.workerCount;
|
|
7335
7346
|
}
|
|
7336
7347
|
function requestThreadCountOf(state) {
|
|
7348
|
+
if (!state.workersEnabled) return 0;
|
|
7337
7349
|
return resolveRequestThreadCount(state.config?.workers?.count);
|
|
7338
7350
|
}
|
|
7339
7351
|
function stopRequestThreads(state) {
|
|
@@ -8275,6 +8287,16 @@ function createEngineCore(config, hooks) {
|
|
|
8275
8287
|
}
|
|
8276
8288
|
|
|
8277
8289
|
// src/engine/index-lifecycle.ts
|
|
8290
|
+
async function runLifecycleHook(core, hookName, context) {
|
|
8291
|
+
try {
|
|
8292
|
+
await core.pluginRegistry.runHook(hookName, context);
|
|
8293
|
+
} catch (err) {
|
|
8294
|
+
console.warn(`${hookName} plugin hook error:`, err instanceof Error ? err.message : String(err));
|
|
8295
|
+
}
|
|
8296
|
+
}
|
|
8297
|
+
async function announceIndexCreated(core, name, config) {
|
|
8298
|
+
await runLifecycleHook(core, "onIndexCreate", { indexName: name, config });
|
|
8299
|
+
}
|
|
8278
8300
|
async function createEngineIndex(core, config, name, indexConfig, indexUuid) {
|
|
8279
8301
|
core.guardShutdown();
|
|
8280
8302
|
validateIndexName(name);
|
|
@@ -8346,7 +8368,7 @@ async function createEngineIndex(core, config, name, indexConfig, indexUuid) {
|
|
|
8346
8368
|
if (core.durability) {
|
|
8347
8369
|
await core.durability.manager.persistMetadata(name);
|
|
8348
8370
|
}
|
|
8349
|
-
await core
|
|
8371
|
+
await runLifecycleHook(core, "onIndexCreate", { indexName: name, config: indexConfig });
|
|
8350
8372
|
}
|
|
8351
8373
|
async function dropEngineIndex(core, name) {
|
|
8352
8374
|
core.guardShutdown();
|
|
@@ -8366,7 +8388,7 @@ async function dropEngineIndex(core, name) {
|
|
|
8366
8388
|
core.watermarkNotifier.forget(name);
|
|
8367
8389
|
core.analysisRebuild.clearStale(name);
|
|
8368
8390
|
});
|
|
8369
|
-
await core
|
|
8391
|
+
await runLifecycleHook(core, "onIndexDrop", { indexName: name, config: entry.config });
|
|
8370
8392
|
}
|
|
8371
8393
|
function registerEngineEmbeddingAdapter(core, name, adapter) {
|
|
8372
8394
|
core.guardShutdown();
|
|
@@ -8487,7 +8509,15 @@ async function awaitWriteVisibility(ctx, indexName) {
|
|
|
8487
8509
|
async function insertDocument(ctx, indexName, document, docId, options) {
|
|
8488
8510
|
ctx.guardShutdown();
|
|
8489
8511
|
const entry = ctx.requireIndex(indexName);
|
|
8490
|
-
const
|
|
8512
|
+
const embeddedDocId = providedDocId(document);
|
|
8513
|
+
if (docId !== void 0 && embeddedDocId !== void 0 && embeddedDocId !== docId) {
|
|
8514
|
+
throw new NarsilError(
|
|
8515
|
+
ErrorCodes.DOC_VALIDATION_FAILED,
|
|
8516
|
+
`The call names document id "${docId}" while the document's own id field is "${embeddedDocId}", so the stored document would contradict the key that it is stored under`,
|
|
8517
|
+
{ docId, documentId: embeddedDocId }
|
|
8518
|
+
);
|
|
8519
|
+
}
|
|
8520
|
+
const resolvedDocId = docId ?? embeddedDocId ?? ctx.idGenerator();
|
|
8491
8521
|
validateDocId(resolvedDocId);
|
|
8492
8522
|
await ctx.pluginRegistry.runHook("beforeInsert", { indexName, docId: resolvedDocId, document });
|
|
8493
8523
|
if (entry.config.required && entry.config.required.length > 0) {
|
|
@@ -8758,13 +8788,12 @@ async function admitBatchDocuments(ctx, indexName, documents, failed) {
|
|
|
8758
8788
|
// src/engine/mutations/insert-batch-documents.ts
|
|
8759
8789
|
async function applyAdmittedDocuments(ctx, indexName, admitted, options, failed) {
|
|
8760
8790
|
const hasAfterHook = ctx.pluginRegistry.hasHooks("afterInsert");
|
|
8761
|
-
const chunkSize = hasAfterHook ? 1 : BATCH_CHUNK_SIZE;
|
|
8762
8791
|
const succeeded = [];
|
|
8763
8792
|
const buffered = /* @__PURE__ */ new Set();
|
|
8764
8793
|
const touchedVectorFields = /* @__PURE__ */ new Set();
|
|
8765
|
-
for (let chunkStart = 0; chunkStart < admitted.length; chunkStart +=
|
|
8794
|
+
for (let chunkStart = 0; chunkStart < admitted.length; chunkStart += BATCH_CHUNK_SIZE) {
|
|
8766
8795
|
if (ctx.abortController.signal.aborted) break;
|
|
8767
|
-
const chunk = admitted.slice(chunkStart, chunkStart +
|
|
8796
|
+
const chunk = admitted.slice(chunkStart, chunkStart + BATCH_CHUNK_SIZE);
|
|
8768
8797
|
const applications = await applyInsertChunk(ctx, indexName, chunk, options);
|
|
8769
8798
|
for (let i = 0; i < chunk.length; i++) {
|
|
8770
8799
|
const doc = chunk[i];
|
|
@@ -8791,8 +8820,8 @@ async function applyAdmittedDocuments(ctx, indexName, admitted, options, failed)
|
|
|
8791
8820
|
}
|
|
8792
8821
|
succeeded.push(doc.docId);
|
|
8793
8822
|
}
|
|
8794
|
-
const applied = chunkStart +
|
|
8795
|
-
if (applied < admitted.length
|
|
8823
|
+
const applied = chunkStart + BATCH_CHUNK_SIZE;
|
|
8824
|
+
if (applied < admitted.length) {
|
|
8796
8825
|
await new Promise((r) => setTimeout(r, 0));
|
|
8797
8826
|
}
|
|
8798
8827
|
}
|
|
@@ -9161,7 +9190,6 @@ async function insertDocumentBatch(ctx, indexName, documents, options) {
|
|
|
9161
9190
|
const failed = [];
|
|
9162
9191
|
const hasBeforeHook = ctx.pluginRegistry.hasHooks("beforeInsert");
|
|
9163
9192
|
const hasAfterHook = ctx.pluginRegistry.hasHooks("afterInsert");
|
|
9164
|
-
const documentByDocument = hasBeforeHook || hasAfterHook;
|
|
9165
9193
|
const required = entry.config.required;
|
|
9166
9194
|
const batchManager = ctx.requireManager(indexName);
|
|
9167
9195
|
const batchVecIndexes = batchManager.getVectorIndexes();
|
|
@@ -9241,9 +9269,6 @@ async function insertDocumentBatch(ctx, indexName, documents, options) {
|
|
|
9241
9269
|
} catch (err) {
|
|
9242
9270
|
failed.push({ docId: batchDocId, error: asBatchInsertError(err) });
|
|
9243
9271
|
}
|
|
9244
|
-
if (documentByDocument && prepared.length > 0) {
|
|
9245
|
-
await applyPrepared(prepared.splice(0, prepared.length));
|
|
9246
|
-
}
|
|
9247
9272
|
}
|
|
9248
9273
|
if (prepared.length > 0) await applyPrepared(prepared);
|
|
9249
9274
|
if (chunkEnd < documents.length) {
|
|
@@ -9358,12 +9383,10 @@ async function removeDocumentBatch(ctx, indexName, docIds, options) {
|
|
|
9358
9383
|
const succeeded = [];
|
|
9359
9384
|
const failed = [];
|
|
9360
9385
|
const manager = ctx.requireManager(indexName);
|
|
9361
|
-
const hooked = ctx.pluginRegistry.hasHooks("beforeRemove") || ctx.pluginRegistry.hasHooks("afterRemove");
|
|
9362
|
-
const chunkSize = hooked ? 1 : BATCH_CHUNK_SIZE;
|
|
9363
9386
|
manager.beginBatchRemove();
|
|
9364
9387
|
try {
|
|
9365
|
-
for (let chunkStart = 0; chunkStart < docIds.length; chunkStart +=
|
|
9366
|
-
const chunkEnd = Math.min(chunkStart +
|
|
9388
|
+
for (let chunkStart = 0; chunkStart < docIds.length; chunkStart += BATCH_CHUNK_SIZE) {
|
|
9389
|
+
const chunkEnd = Math.min(chunkStart + BATCH_CHUNK_SIZE, docIds.length);
|
|
9367
9390
|
const prepared = [];
|
|
9368
9391
|
for (let i = chunkStart; i < chunkEnd; i++) {
|
|
9369
9392
|
try {
|
|
@@ -9390,13 +9413,14 @@ async function removeDocumentBatch(ctx, indexName, docIds, options) {
|
|
|
9390
9413
|
if (!removal.buffered) await settleRemoval(ctx, indexName, removal.docId);
|
|
9391
9414
|
succeeded.push(removal.docId);
|
|
9392
9415
|
}
|
|
9393
|
-
if (chunkEnd < docIds.length
|
|
9416
|
+
if (chunkEnd < docIds.length) {
|
|
9394
9417
|
await new Promise((r) => setTimeout(r, 0));
|
|
9395
9418
|
}
|
|
9396
9419
|
}
|
|
9397
9420
|
} finally {
|
|
9398
9421
|
manager.endBatchRemove();
|
|
9399
9422
|
}
|
|
9423
|
+
ctx.checkHeapPressure(indexName);
|
|
9400
9424
|
if (options?.wait === true) await awaitWriteVisibility(ctx, indexName);
|
|
9401
9425
|
return { succeeded, failed };
|
|
9402
9426
|
}
|
|
@@ -9557,10 +9581,8 @@ async function updateDocumentBatch(ctx, indexName, updates, options) {
|
|
|
9557
9581
|
const updateBatchManager = ctx.requireManager(indexName);
|
|
9558
9582
|
const updateBatchVecIndexes = updateBatchManager.getVectorIndexes();
|
|
9559
9583
|
const touchedVectorFields = /* @__PURE__ */ new Set();
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
for (let chunkStart = 0; chunkStart < updates.length; chunkStart += chunkSize) {
|
|
9563
|
-
const chunkEnd = Math.min(chunkStart + chunkSize, updates.length);
|
|
9584
|
+
for (let chunkStart = 0; chunkStart < updates.length; chunkStart += BATCH_CHUNK_SIZE) {
|
|
9585
|
+
const chunkEnd = Math.min(chunkStart + BATCH_CHUNK_SIZE, updates.length);
|
|
9564
9586
|
const prepared = [];
|
|
9565
9587
|
for (let i = chunkStart; i < chunkEnd; i++) {
|
|
9566
9588
|
try {
|
|
@@ -9590,7 +9612,7 @@ async function updateDocumentBatch(ctx, indexName, updates, options) {
|
|
|
9590
9612
|
}
|
|
9591
9613
|
succeeded.push(update.docId);
|
|
9592
9614
|
}
|
|
9593
|
-
if (chunkEnd < updates.length
|
|
9615
|
+
if (chunkEnd < updates.length) {
|
|
9594
9616
|
await new Promise((r) => setTimeout(r, 0));
|
|
9595
9617
|
}
|
|
9596
9618
|
}
|
|
@@ -10225,6 +10247,7 @@ async function restoreFromSnapshot(indexName, data, deps) {
|
|
|
10225
10247
|
await deps.durability.manager.persistMetadata(indexName);
|
|
10226
10248
|
await deps.durability.manager.checkpoint(indexName);
|
|
10227
10249
|
}
|
|
10250
|
+
await deps.announceIndexCreated(indexName, indexConfig);
|
|
10228
10251
|
} catch (err) {
|
|
10229
10252
|
try {
|
|
10230
10253
|
deps.executor.dropIndex(indexName);
|
|
@@ -10296,13 +10319,14 @@ function readProcessMemory() {
|
|
|
10296
10319
|
}
|
|
10297
10320
|
try {
|
|
10298
10321
|
const usage = proc.memoryUsage();
|
|
10322
|
+
const heap = readHeapStatistics();
|
|
10299
10323
|
if (!Number.isFinite(usage.heapUsed) || !Number.isFinite(usage.heapTotal) || !Number.isFinite(usage.external) || !Number.isFinite(usage.rss)) {
|
|
10300
10324
|
return null;
|
|
10301
10325
|
}
|
|
10302
10326
|
return {
|
|
10303
10327
|
heapUsed: usage.heapUsed,
|
|
10304
10328
|
heapTotal: usage.heapTotal,
|
|
10305
|
-
heapLimit:
|
|
10329
|
+
heapLimit: heap === null ? null : heap.configuredLimitBytes ?? heap.limitBytes,
|
|
10306
10330
|
external: usage.external,
|
|
10307
10331
|
rss: usage.rss
|
|
10308
10332
|
};
|
|
@@ -10335,13 +10359,14 @@ async function runEngineQuery(core, indexName, params, options) {
|
|
|
10335
10359
|
try {
|
|
10336
10360
|
const entry = core.requireIndex(indexName);
|
|
10337
10361
|
const manager = core.requireManager(indexName);
|
|
10362
|
+
const scoped = scopedParams(params, options);
|
|
10363
|
+
await core.pluginRegistry.runHook("beforeSearch", { indexName, params: scoped });
|
|
10338
10364
|
const resolvedParams = await resolveVectorText(
|
|
10339
|
-
|
|
10365
|
+
scoped,
|
|
10340
10366
|
entry.embeddingAdapter,
|
|
10341
10367
|
core.abortController.signal,
|
|
10342
10368
|
entry.embeddingAdapterName
|
|
10343
10369
|
);
|
|
10344
|
-
await core.pluginRegistry.runHook("beforeSearch", { indexName, params: resolvedParams });
|
|
10345
10370
|
const workerSearch = core.orchestrator.hasWorkerPool() ? core.orchestrator.searchViaWorker.bind(core.orchestrator) : void 0;
|
|
10346
10371
|
const result = await executeQuery(resolvedParams, {
|
|
10347
10372
|
manager,
|
|
@@ -10353,14 +10378,13 @@ async function runEngineQuery(core, indexName, params, options) {
|
|
|
10353
10378
|
partitionIds: options?.partitionIds,
|
|
10354
10379
|
cursorBinding: queryBindingOf(params)
|
|
10355
10380
|
});
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
params: resolvedParams,
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
console.warn("afterSearch plugin hook error:", err);
|
|
10381
|
+
if (core.pluginRegistry.hasHooks("afterSearch")) {
|
|
10382
|
+
const observed = { ...result, hits: [...result.hits] };
|
|
10383
|
+
try {
|
|
10384
|
+
await core.pluginRegistry.runHook("afterSearch", { indexName, params: resolvedParams, results: observed });
|
|
10385
|
+
} catch (err) {
|
|
10386
|
+
console.warn("afterSearch plugin hook error:", err);
|
|
10387
|
+
}
|
|
10364
10388
|
}
|
|
10365
10389
|
if (core.analysisRebuild.isStale(indexName)) {
|
|
10366
10390
|
result.analysisStale = true;
|
|
@@ -10376,8 +10400,10 @@ async function runEnginePreflight(core, indexName, params, options) {
|
|
|
10376
10400
|
try {
|
|
10377
10401
|
const entry = core.requireIndex(indexName);
|
|
10378
10402
|
const manager = core.requireManager(indexName);
|
|
10403
|
+
const scoped = scopedParams(params, options);
|
|
10404
|
+
await core.pluginRegistry.runHook("beforeSearch", { indexName, params: scoped });
|
|
10379
10405
|
const resolvedParams = await resolveVectorText(
|
|
10380
|
-
|
|
10406
|
+
scoped,
|
|
10381
10407
|
entry.embeddingAdapter,
|
|
10382
10408
|
core.abortController.signal,
|
|
10383
10409
|
entry.embeddingAdapterName
|
|
@@ -10616,6 +10642,7 @@ function createNarsilFromCore(core, config) {
|
|
|
10616
10642
|
indexRegistry,
|
|
10617
10643
|
getVectorFieldPaths,
|
|
10618
10644
|
dropIndex: narsil.dropIndex.bind(narsil),
|
|
10645
|
+
announceIndexCreated: (name, restoredConfig) => announceIndexCreated(core, name, restoredConfig),
|
|
10619
10646
|
requireManager,
|
|
10620
10647
|
durability,
|
|
10621
10648
|
filesystemDurability: core.filesystemDurability,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_PAGE_SIZE } from './chunk-
|
|
1
|
+
import { DEFAULT_PAGE_SIZE } from './chunk-L225SHNB.mjs';
|
|
2
2
|
|
|
3
3
|
// src/engine/constants.ts
|
|
4
4
|
var MIN_DOCUMENTS_FOR_SEGMENTS = 64;
|
|
@@ -6,6 +6,8 @@ var BATCH_CHUNK_SIZE = 1e3;
|
|
|
6
6
|
var DEFAULT_LIMIT = DEFAULT_PAGE_SIZE;
|
|
7
7
|
var DEFAULT_OFFSET = 0;
|
|
8
8
|
var INDEX_NAME_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
9
|
+
var ABSOLUTE_WINDOWS_PATH_PATTERN = /^[a-zA-Z]:[\\/]/;
|
|
10
|
+
var MODULE_URL_SCHEME_PATTERN = /^(file|https?|data|node):/;
|
|
9
11
|
var MAX_INDEX_NAME_LENGTH = 255;
|
|
10
12
|
var MAX_DOC_ID_LENGTH = 512;
|
|
11
13
|
var MIN_SWEEP_INTERVAL_MS = 100;
|
|
@@ -20,4 +22,4 @@ var SUGGEST_OVERSAMPLE_FACTOR = 1.5;
|
|
|
20
22
|
var SUGGEST_OVERSAMPLE_PADDING = 10;
|
|
21
23
|
var MAX_SUGGEST_SCATTER_LIMIT = Math.ceil(MAX_SUGGEST_LIMIT * SUGGEST_OVERSAMPLE_FACTOR) + SUGGEST_OVERSAMPLE_PADDING;
|
|
22
24
|
|
|
23
|
-
export { BATCH_CHUNK_SIZE, DEFAULT_LIMIT, DEFAULT_OFFSET, DEFAULT_SUGGEST_LIMIT, FOREIGN_STATS_TTL_MS, HEAP_PRESSURE_REARM_FRACTION, HEAP_PRESSURE_WARNING_FRACTION, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, MAX_INDEX_NAME_LENGTH, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, MAX_SWEEP_INTERVAL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, MIN_SWEEP_INTERVAL_MS, STATISTICS_BROADCAST_INTERVAL_MS, SUGGEST_OVERSAMPLE_FACTOR, SUGGEST_OVERSAMPLE_PADDING };
|
|
25
|
+
export { ABSOLUTE_WINDOWS_PATH_PATTERN, BATCH_CHUNK_SIZE, DEFAULT_LIMIT, DEFAULT_OFFSET, DEFAULT_SUGGEST_LIMIT, FOREIGN_STATS_TTL_MS, HEAP_PRESSURE_REARM_FRACTION, HEAP_PRESSURE_WARNING_FRACTION, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, MAX_INDEX_NAME_LENGTH, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, MAX_SWEEP_INTERVAL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, MIN_SWEEP_INTERVAL_MS, MODULE_URL_SCHEME_PATTERN, STATISTICS_BROADCAST_INTERVAL_MS, SUGGEST_OVERSAMPLE_FACTOR, SUGGEST_OVERSAMPLE_PADDING };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/errors.ts
|
|
2
|
+
var NARSIL_ERROR_MARKER = /* @__PURE__ */ Symbol.for("@delali/narsil.NarsilError");
|
|
2
3
|
var ErrorCodes = {
|
|
3
4
|
SCHEMA_INVALID_TYPE: "SCHEMA_INVALID_TYPE",
|
|
4
5
|
SCHEMA_DEPTH_EXCEEDED: "SCHEMA_DEPTH_EXCEEDED",
|
|
@@ -16,6 +17,7 @@ var ErrorCodes = {
|
|
|
16
17
|
WORKER_CRASHED: "WORKER_CRASHED",
|
|
17
18
|
WORKER_BUSY: "WORKER_BUSY",
|
|
18
19
|
WORKER_TIMEOUT: "WORKER_TIMEOUT",
|
|
20
|
+
WORKER_ACTION_FAILED: "WORKER_ACTION_FAILED",
|
|
19
21
|
PERSISTENCE_SAVE_FAILED: "PERSISTENCE_SAVE_FAILED",
|
|
20
22
|
PERSISTENCE_LOAD_FAILED: "PERSISTENCE_LOAD_FAILED",
|
|
21
23
|
PERSISTENCE_DELETE_FAILED: "PERSISTENCE_DELETE_FAILED",
|
|
@@ -135,8 +137,12 @@ var NarsilError = class extends Error {
|
|
|
135
137
|
this.name = "NarsilError";
|
|
136
138
|
this.code = code;
|
|
137
139
|
this.details = details ?? {};
|
|
140
|
+
Object.defineProperty(this, NARSIL_ERROR_MARKER, { value: true });
|
|
138
141
|
}
|
|
139
142
|
};
|
|
143
|
+
function isNarsilError(value) {
|
|
144
|
+
return typeof value === "object" && value !== null && NARSIL_ERROR_MARKER in value;
|
|
145
|
+
}
|
|
140
146
|
function createNarsilError(code, message, details) {
|
|
141
147
|
return new NarsilError(code, message, details);
|
|
142
148
|
}
|
|
@@ -144,4 +150,4 @@ function describeError(error) {
|
|
|
144
150
|
return error instanceof Error ? error.message : String(error);
|
|
145
151
|
}
|
|
146
152
|
|
|
147
|
-
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, createNarsilError, describeError };
|
|
153
|
+
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, createNarsilError, describeError, isNarsilError };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MAX_M } from './chunk-
|
|
2
|
-
import { NarsilError, ErrorCodes } from './chunk-
|
|
1
|
+
import { MAX_M } from './chunk-UTOFOJOR.mjs';
|
|
2
|
+
import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
|
|
3
3
|
|
|
4
4
|
// src/schema/constants.ts
|
|
5
5
|
var MAX_NESTING_DEPTH = 4;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR } from './chunk-
|
|
2
|
-
import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN } from './chunk-
|
|
3
|
-
import { NarsilError, ErrorCodes } from './chunk-
|
|
1
|
+
import { MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR } from './chunk-4NVPQ6S5.mjs';
|
|
2
|
+
import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN } from './chunk-D2S642IV.mjs';
|
|
3
|
+
import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
|
|
4
4
|
import { encode, decode } from '@msgpack/msgpack';
|
|
5
5
|
|
|
6
6
|
var INDEX_CONFIG_PREFIX = "_narsil/index/";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { MAX_SORT_FIELDS } from './chunk-
|
|
2
|
-
import {
|
|
1
|
+
import { MAX_SORT_FIELDS } from './chunk-L225SHNB.mjs';
|
|
2
|
+
import { nativeSearchCoreIsEnabled, loadNativeCore } from './chunk-UTOFOJOR.mjs';
|
|
3
|
+
import { NarsilError, ServerErrorCodes, ErrorCodes } from './chunk-FRQVMFY7.mjs';
|
|
3
4
|
|
|
4
5
|
// src/server/capabilities.ts
|
|
5
6
|
var ASYNC_IMPORT_CAPABILITY = "documents.import.async";
|
|
@@ -122,6 +123,7 @@ var STATUS_BY_CODE = {
|
|
|
122
123
|
PARTITION_CORRUPTED: 503,
|
|
123
124
|
WORKER_CRASHED: 503,
|
|
124
125
|
WORKER_TIMEOUT: 503,
|
|
126
|
+
WORKER_ACTION_FAILED: 500,
|
|
125
127
|
PERSISTENCE_SAVE_FAILED: 503,
|
|
126
128
|
PERSISTENCE_LOAD_FAILED: 503,
|
|
127
129
|
PERSISTENCE_DELETE_FAILED: 503,
|
|
@@ -224,6 +226,8 @@ var DEFAULT_MAX_FETCH_DOCUMENTS = 1e4;
|
|
|
224
226
|
var DEFAULT_MAX_IMPORT_ERRORS = 100;
|
|
225
227
|
var DEFAULT_MAX_TASK_PAGE_SIZE = 1e3;
|
|
226
228
|
var DEFAULT_MAX_CONCURRENT_TASKS = 4;
|
|
229
|
+
var MIN_COUNTED_SERVER_LIMIT = 1;
|
|
230
|
+
var MIN_UNBOUNDED_SERVER_LIMIT = 0;
|
|
227
231
|
var RESPONSE_STREAM_THRESHOLD_BYTES = 64 * 1024;
|
|
228
232
|
var MAX_INDEX_TOUCH_INTERVAL_MS = 1e3;
|
|
229
233
|
var INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT = 4;
|
|
@@ -484,7 +488,7 @@ function validateRebalance(body) {
|
|
|
484
488
|
return null;
|
|
485
489
|
}
|
|
486
490
|
var TASK_TYPES = ["optimizeVectors", "rebalance", "restore", "import", "rebuildAnalysis"];
|
|
487
|
-
var TASK_STATUSES = ["
|
|
491
|
+
var TASK_STATUSES = ["running", "succeeded", "failed", "cancelled"];
|
|
488
492
|
function parseCountParam(raw, field, minimum) {
|
|
489
493
|
if (raw === null) return minimum;
|
|
490
494
|
const value = Number(raw);
|
|
@@ -603,6 +607,22 @@ function indexDocNotFound(docId) {
|
|
|
603
607
|
return new NarsilError(ErrorCodes.DOC_NOT_FOUND, `Document "${docId}" not found`, { docId });
|
|
604
608
|
}
|
|
605
609
|
|
|
610
|
+
// src/vector/native/search-path.ts
|
|
611
|
+
function vectorSearchPath() {
|
|
612
|
+
return nativeSearchCoreIsEnabled() && loadNativeCore() !== null ? "native" : "wasm";
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// src/server/handlers/version.ts
|
|
616
|
+
function versionReport(build) {
|
|
617
|
+
return { name: "narsil", ...build, vectorSearch: vectorSearchPath() };
|
|
618
|
+
}
|
|
619
|
+
function createVersionHandler(deps) {
|
|
620
|
+
function report(ctx) {
|
|
621
|
+
respondJson(ctx, versionReport(deps.build));
|
|
622
|
+
}
|
|
623
|
+
return { report };
|
|
624
|
+
}
|
|
625
|
+
|
|
606
626
|
// src/server/request.ts
|
|
607
627
|
function initAbortHandler(res) {
|
|
608
628
|
const listeners = [];
|
|
@@ -790,7 +810,7 @@ function serverRoutes(limits) {
|
|
|
790
810
|
return [
|
|
791
811
|
{ method: "get", path: "/livez", handler: "livez", options: probe },
|
|
792
812
|
{ method: "get", path: "/readyz", handler: "readyz", options: probe },
|
|
793
|
-
{ method: "get", path: "/health", handler: "
|
|
813
|
+
{ method: "get", path: "/health", handler: "readyz", options: probe },
|
|
794
814
|
{ method: "get", path: "/version", handler: "version", options: probe },
|
|
795
815
|
{ method: "get", path: "/capabilities", handler: "capabilities", options: probe },
|
|
796
816
|
{ method: "get", path: "/cluster", handler: "clusterTopology", options: bare },
|
|
@@ -896,4 +916,4 @@ function childAppOf(app) {
|
|
|
896
916
|
return candidate;
|
|
897
917
|
}
|
|
898
918
|
|
|
899
|
-
export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, REBUILD_ANALYSIS_CAPABILITY, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsWriter, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendBinary, sendError, sendRelayed, serializeBatchResult, serializeNarsilError, serverRoutes, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest };
|
|
919
|
+
export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, MIN_COUNTED_SERVER_LIMIT, MIN_UNBOUNDED_SERVER_LIMIT, REBUILD_ANALYSIS_CAPABILITY, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsWriter, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, createVersionHandler, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendBinary, sendError, sendRelayed, serializeBatchResult, serializeNarsilError, serverRoutes, toHttpError, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest, versionReport };
|