@delali/narsil 0.2.4-next.47 → 0.2.4-next.49
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/indexeddb.mjs +15 -10
- package/dist/{chunk-BFIH7OV5.mjs → chunk-2GWVQWGA.mjs} +3 -1
- package/dist/{chunk-UZTT2BKQ.mjs → chunk-56PJBIJ6.mjs} +891 -542
- package/dist/chunk-CBLS46IE.mjs +10 -0
- package/dist/{chunk-JQUL2T6I.mjs → chunk-GCM3JFVA.mjs} +1 -2
- package/dist/{chunk-4COAUBLJ.mjs → chunk-HGJC5L65.mjs} +4 -7
- package/dist/{chunk-DFZDV5FV.mjs → chunk-JXHUHFJ5.mjs} +27 -14
- package/dist/{chunk-XWICBGYT.mjs → chunk-KGRYQVZ5.mjs} +2 -5
- package/dist/{chunk-EV45L35L.mjs → chunk-M6JGMKA5.mjs} +391 -183
- package/dist/{chunk-PM52SMBT.mjs → chunk-OOSIDHA3.mjs} +2 -1
- package/dist/chunk-ORBLD3EL.mjs +6 -0
- package/dist/chunk-OWCFK42Q.mjs +30 -0
- package/dist/{chunk-WTONLDU3.mjs → chunk-RDGXYRF4.mjs} +1 -0
- package/dist/chunk-UNEEFTEU.mjs +7 -0
- package/dist/chunk-YEO6G2NG.mjs +6 -0
- package/dist/{client-C5BkUqB8.d.ts → client-DX7xPcNA.d.ts} +1 -1
- package/dist/client.d.ts +5 -5
- package/dist/client.mjs +224 -222
- package/dist/{config-B-ZI-ft5.d.ts → config-B41W23Us.d.ts} +1 -1
- package/dist/{config-BZRExglL.d.ts → config-Co-zAXqO.d.ts} +27 -11
- package/dist/direct-executor-HRTDWMVB.mjs +9 -0
- package/dist/distribution/coordinator/etcd.mjs +4 -7
- package/dist/distribution/coordinator/in-memory.mjs +2 -2
- package/dist/distribution/transport/grpc.mjs +7 -9
- package/dist/distribution/transport/in-memory.mjs +2 -1
- package/dist/distribution/transport/tcp.mjs +3 -2
- package/dist/distribution.d.ts +5 -5
- package/dist/distribution.mjs +121 -97
- package/dist/embeddings/openai.mjs +5 -3
- package/dist/{engine-Cjr1uBLa.d.ts → engine-CABZg25p.d.ts} +12 -8
- package/dist/index.browser.mjs +1514 -894
- package/dist/index.d.ts +5 -5
- package/dist/index.mjs +9 -8
- package/dist/invalidation/broadcast-channel.mjs +2 -1
- package/dist/invalidation/filesystem.mjs +3 -4
- package/dist/{options-BC68VPoE.d.ts → options-Dtk99qUs.d.ts} +1 -1
- package/dist/persistence/durability/checkpoint-worker.mjs +9 -8
- package/dist/react.d.ts +3 -3
- package/dist/react.mjs +7 -5
- package/dist/{search-DDHjfXhJ.d.ts → search-FjWhZN3f.d.ts} +20 -3
- package/dist/server.d.ts +6 -6
- package/dist/server.mjs +43 -30
- package/dist/vector/hnsw-build-worker.mjs +2 -4
- package/dist/vector/search-worker.mjs +3 -4
- package/dist/workers/entry.mjs +2 -2
- package/package.json +1 -1
- package/dist/direct-executor-EOTFGXTO.mjs +0 -8
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, RESULT_WINDOW, DEFAULT_PAGE_SIZE, PREFIX_MAX_EXPANSIONS, MAX_CURSOR_ANCHOR_CODE_POINTS } from './chunk-CBLS46IE.mjs';
|
|
1
2
|
import { english } from './chunk-TGP5M5R7.mjs';
|
|
2
|
-
import { createScalarQuantizer } from './chunk-
|
|
3
|
-
import { MAX_M, createVectorStore, createHNSWIndex, createOrdinalFilter, addToOrdinalFilter, removeFromOrdinalFilter, ordinalFilterValues, magnitude, toScore, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, ABSENT_DOCUMENT_RANK } from './chunk-
|
|
4
|
-
import { compareCodePoints, compareComparableKeys, toComparableSortValue, readSortField, compareSortValues, compareComparableValues
|
|
5
|
-
import { generateId, createRequestId } from './chunk-
|
|
3
|
+
import { createScalarQuantizer } from './chunk-HGJC5L65.mjs';
|
|
4
|
+
import { MAX_M, createVectorStore, createHNSWIndex, createOrdinalFilter, addToOrdinalFilter, removeFromOrdinalFilter, ordinalFilterValues, magnitude, toScore, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, WASM_PAGE_BYTES, ABSENT_DOCUMENT_RANK, HNSW_BUILD_TIMEOUT_MS, VECTOR_SEARCH_LOAD_TIMEOUT_MS, MAX_WASM_PAGES, VECTOR_SEARCH_TIMEOUT_MS } from './chunk-JXHUHFJ5.mjs';
|
|
5
|
+
import { compareCodePoints, compareComparableKeys, toComparableSortValue, readSortField, SORT_VALUE_MAX_CODE_POINTS, compareSortValues, compareComparableValues } from './chunk-2GWVQWGA.mjs';
|
|
6
|
+
import { generateId, createRequestId } from './chunk-RDGXYRF4.mjs';
|
|
6
7
|
import { NarsilError, ErrorCodes, createNarsilError } from './chunk-P4ELXVJQ.mjs';
|
|
7
8
|
import { encode, decode } from '@msgpack/msgpack';
|
|
8
9
|
|
|
@@ -27,7 +28,6 @@ var VECTOR_PATTERN = /^vector\[(\d+)]$/;
|
|
|
27
28
|
var FIELD_NAME_PATTERN = /^[A-Za-z0-9_]+$/;
|
|
28
29
|
var RESERVED_ROOT_FIELDS = /* @__PURE__ */ new Set(["id"]);
|
|
29
30
|
var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
30
|
-
var MAX_NESTING_DEPTH = 4;
|
|
31
31
|
function isPlainObject(value) {
|
|
32
32
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33
33
|
}
|
|
@@ -199,8 +199,11 @@ function validateFieldValue(path, value, type) {
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
// src/schema/
|
|
202
|
+
// src/schema/constants.ts
|
|
203
|
+
var MAX_NESTING_DEPTH = 4;
|
|
203
204
|
var MAX_DOCUMENT_NESTING_DEPTH = 32;
|
|
205
|
+
|
|
206
|
+
// src/schema/validator/storable.ts
|
|
204
207
|
var RESERVED_OBJECT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
205
208
|
function reject(path, reason) {
|
|
206
209
|
throw new NarsilError(ErrorCodes.DOC_VALIDATION_FAILED, `Field "${path === "" ? "(document)" : path}" ${reason}`, {
|
|
@@ -484,6 +487,11 @@ function validateVectorPromotion(config) {
|
|
|
484
487
|
fail("vectorPromotion.hnswConfig.metric must be 'cosine', 'dotProduct', or 'euclidean'", { metric });
|
|
485
488
|
}
|
|
486
489
|
}
|
|
490
|
+
|
|
491
|
+
// src/serialization/constants.ts
|
|
492
|
+
var CHECKSUM_TIMEOUT_MS = 12e4;
|
|
493
|
+
var CHECKSUM_YIELD_CHUNK_BYTES = 4 * 1024 * 1024;
|
|
494
|
+
var VALID_HNSW_METRICS = /* @__PURE__ */ new Set(["cosine", "dotProduct", "euclidean"]);
|
|
487
495
|
function metadataToWire(meta) {
|
|
488
496
|
const wire = {
|
|
489
497
|
index_name: meta.indexName,
|
|
@@ -726,7 +734,6 @@ function sanitizeSurfaceForms(raw) {
|
|
|
726
734
|
}
|
|
727
735
|
return count > 0 ? result : void 0;
|
|
728
736
|
}
|
|
729
|
-
var VALID_HNSW_METRICS = /* @__PURE__ */ new Set(["cosine", "dotProduct", "euclidean"]);
|
|
730
737
|
function validateHnswMetric(value) {
|
|
731
738
|
if (value === void 0 || value === null) return void 0;
|
|
732
739
|
if (typeof value === "string" && VALID_HNSW_METRICS.has(value)) {
|
|
@@ -824,10 +831,9 @@ function deserializePayloadV1(data) {
|
|
|
824
831
|
function encodeRawPayloadV2(wire) {
|
|
825
832
|
return encode(wire);
|
|
826
833
|
}
|
|
827
|
-
var VALID_HNSW_METRICS2 = /* @__PURE__ */ new Set(["cosine", "dotProduct", "euclidean"]);
|
|
828
834
|
function validateHnswMetric2(value) {
|
|
829
835
|
if (value === void 0 || value === null) return void 0;
|
|
830
|
-
if (typeof value === "string" &&
|
|
836
|
+
if (typeof value === "string" && VALID_HNSW_METRICS.has(value)) {
|
|
831
837
|
return value;
|
|
832
838
|
}
|
|
833
839
|
return void 0;
|
|
@@ -1168,6 +1174,11 @@ function createDocumentStore() {
|
|
|
1168
1174
|
};
|
|
1169
1175
|
}
|
|
1170
1176
|
|
|
1177
|
+
// src/core/constants.ts
|
|
1178
|
+
var POSTING_LIST_INITIAL_CAPACITY = 8;
|
|
1179
|
+
var POSTING_LIST_COMPACTION_THRESHOLD = 0.3;
|
|
1180
|
+
var MAX_TERM_FREQUENCY = 65535;
|
|
1181
|
+
|
|
1171
1182
|
// src/core/fuzzy.ts
|
|
1172
1183
|
function boundedLevenshtein(a, b, tolerance) {
|
|
1173
1184
|
if (tolerance < 0) return { distance: -1, withinTolerance: false };
|
|
@@ -1218,15 +1229,12 @@ function boundedLevenshtein(a, b, tolerance) {
|
|
|
1218
1229
|
}
|
|
1219
1230
|
|
|
1220
1231
|
// src/core/posting-list.ts
|
|
1221
|
-
var INITIAL_CAPACITY = 8;
|
|
1222
|
-
var MAX_TERM_FREQUENCY = 65535;
|
|
1223
|
-
var COMPACTION_THRESHOLD = 0.3;
|
|
1224
1232
|
function createPostingList() {
|
|
1225
1233
|
return {
|
|
1226
1234
|
length: 0,
|
|
1227
1235
|
docIds: [],
|
|
1228
|
-
termFrequencies: new Uint16Array(
|
|
1229
|
-
fieldNameIndices: new Uint8Array(
|
|
1236
|
+
termFrequencies: new Uint16Array(POSTING_LIST_INITIAL_CAPACITY),
|
|
1237
|
+
fieldNameIndices: new Uint8Array(POSTING_LIST_INITIAL_CAPACITY),
|
|
1230
1238
|
positions: null,
|
|
1231
1239
|
docIdSet: /* @__PURE__ */ new Set(),
|
|
1232
1240
|
deletedDocs: /* @__PURE__ */ new Set(),
|
|
@@ -1394,7 +1402,7 @@ function createInvertedIndex(fieldNameTable) {
|
|
|
1394
1402
|
batchDirtyTokens.add(token);
|
|
1395
1403
|
return;
|
|
1396
1404
|
}
|
|
1397
|
-
if (list.deletedDocs.size / list.length >
|
|
1405
|
+
if (list.deletedDocs.size / list.length > POSTING_LIST_COMPACTION_THRESHOLD) {
|
|
1398
1406
|
compactList(list);
|
|
1399
1407
|
}
|
|
1400
1408
|
},
|
|
@@ -1407,7 +1415,7 @@ function createInvertedIndex(fieldNameTable) {
|
|
|
1407
1415
|
for (const token of batchDirtyTokens) {
|
|
1408
1416
|
const list = index.get(token);
|
|
1409
1417
|
if (!list) continue;
|
|
1410
|
-
if (list.deletedDocs.size / list.length >
|
|
1418
|
+
if (list.deletedDocs.size / list.length > POSTING_LIST_COMPACTION_THRESHOLD) {
|
|
1411
1419
|
compactList(list);
|
|
1412
1420
|
}
|
|
1413
1421
|
}
|
|
@@ -2190,9 +2198,13 @@ function computeFacets(state, matched, config, schema) {
|
|
|
2190
2198
|
return result;
|
|
2191
2199
|
}
|
|
2192
2200
|
|
|
2201
|
+
// src/geo/constants.ts
|
|
2202
|
+
var DEG_TO_RAD = Math.PI / 180;
|
|
2203
|
+
var VINCENTY_MAX_ITERATIONS = 200;
|
|
2204
|
+
var VINCENTY_CONVERGENCE_THRESHOLD = 1e-12;
|
|
2205
|
+
|
|
2193
2206
|
// src/geo/haversine.ts
|
|
2194
2207
|
var EARTH_RADIUS_METERS = 63710088e-1;
|
|
2195
|
-
var DEG_TO_RAD = Math.PI / 180;
|
|
2196
2208
|
function haversineDistance(lat1, lon1, lat2, lon2) {
|
|
2197
2209
|
const phi1 = lat1 * DEG_TO_RAD;
|
|
2198
2210
|
const phi2 = lat2 * DEG_TO_RAD;
|
|
@@ -2230,13 +2242,10 @@ function isPointInPolygon(lat, lon, polygon) {
|
|
|
2230
2242
|
var WGS84_A = 6378137;
|
|
2231
2243
|
var WGS84_F = 1 / 298.257223563;
|
|
2232
2244
|
var WGS84_B = WGS84_A * (1 - WGS84_F);
|
|
2233
|
-
var DEG_TO_RAD2 = Math.PI / 180;
|
|
2234
|
-
var MAX_ITERATIONS = 200;
|
|
2235
|
-
var CONVERGENCE_THRESHOLD = 1e-12;
|
|
2236
2245
|
function vincentyDistance(lat1, lon1, lat2, lon2) {
|
|
2237
|
-
const phi1 = lat1 *
|
|
2238
|
-
const phi2 = lat2 *
|
|
2239
|
-
const L = (lon2 - lon1) *
|
|
2246
|
+
const phi1 = lat1 * DEG_TO_RAD;
|
|
2247
|
+
const phi2 = lat2 * DEG_TO_RAD;
|
|
2248
|
+
const L = (lon2 - lon1) * DEG_TO_RAD;
|
|
2240
2249
|
const U1 = Math.atan((1 - WGS84_F) * Math.tan(phi1));
|
|
2241
2250
|
const U2 = Math.atan((1 - WGS84_F) * Math.tan(phi2));
|
|
2242
2251
|
const sinU1 = Math.sin(U1);
|
|
@@ -2251,7 +2260,7 @@ function vincentyDistance(lat1, lon1, lat2, lon2) {
|
|
|
2251
2260
|
let sinAlpha = 0;
|
|
2252
2261
|
let cos2Alpha = 0;
|
|
2253
2262
|
let cos2SigmaM = 0;
|
|
2254
|
-
let iterations =
|
|
2263
|
+
let iterations = VINCENTY_MAX_ITERATIONS;
|
|
2255
2264
|
do {
|
|
2256
2265
|
const sinLambda = Math.sin(lambda);
|
|
2257
2266
|
const cosLambda = Math.cos(lambda);
|
|
@@ -2267,7 +2276,7 @@ function vincentyDistance(lat1, lon1, lat2, lon2) {
|
|
|
2267
2276
|
const C = WGS84_F / 16 * cos2Alpha * (4 + WGS84_F * (4 - 3 * cos2Alpha));
|
|
2268
2277
|
prevLambda = lambda;
|
|
2269
2278
|
lambda = L + (1 - C) * WGS84_F * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
|
|
2270
|
-
} while (Math.abs(lambda - prevLambda) >
|
|
2279
|
+
} while (Math.abs(lambda - prevLambda) > VINCENTY_CONVERGENCE_THRESHOLD && --iterations > 0);
|
|
2271
2280
|
if (iterations === 0) {
|
|
2272
2281
|
return haversineDistance(lat1, lon1, lat2, lon2);
|
|
2273
2282
|
}
|
|
@@ -2696,6 +2705,20 @@ function createNumericIndex() {
|
|
|
2696
2705
|
};
|
|
2697
2706
|
}
|
|
2698
2707
|
|
|
2708
|
+
// src/core/tokenizer/constants.ts
|
|
2709
|
+
var TOKEN_CACHE_SIZE_FLOOR = 5e4;
|
|
2710
|
+
var TOKEN_CACHE_SIZE_CEILING = 2e6;
|
|
2711
|
+
var TOKEN_CACHE_BYTES_PER_ENTRY = 200;
|
|
2712
|
+
var NODE_TOKEN_CACHE_ENTRIES = 1e6;
|
|
2713
|
+
var UNKNOWN_MEMORY_TOKEN_CACHE_ENTRIES = 2e5;
|
|
2714
|
+
var CONSTRAINED_MEMORY_TOKEN_CACHE_FRACTION = 0.05;
|
|
2715
|
+
var SMALL_DEVICE_MEMORY_GB = 1;
|
|
2716
|
+
var MEDIUM_DEVICE_MEMORY_GB = 4;
|
|
2717
|
+
var SMALL_DEVICE_TOKEN_CACHE_ENTRIES = 1e5;
|
|
2718
|
+
var MEDIUM_DEVICE_TOKEN_CACHE_ENTRIES = 25e4;
|
|
2719
|
+
var LARGE_DEVICE_TOKEN_CACHE_ENTRIES = 5e5;
|
|
2720
|
+
var DEFAULT_MIN_TOKEN_LENGTH = 1;
|
|
2721
|
+
|
|
2699
2722
|
// src/core/tokenizer/normalize.ts
|
|
2700
2723
|
var DOTTED_CAPITAL_I = "\u0130";
|
|
2701
2724
|
var COMBINING_DOT_ABOVE = "\u0307";
|
|
@@ -2742,37 +2765,33 @@ function stripDiacritics(text) {
|
|
|
2742
2765
|
}
|
|
2743
2766
|
|
|
2744
2767
|
// src/core/tokenizer/cache.ts
|
|
2745
|
-
var CACHE_SIZE_FLOOR = 5e4;
|
|
2746
|
-
var CACHE_SIZE_CEILING = 2e6;
|
|
2747
|
-
var BYTES_PER_ENTRY = 200;
|
|
2748
|
-
var NODE_CACHE_ENTRIES = 1e6;
|
|
2749
|
-
var UNKNOWN_MEMORY_CACHE_ENTRIES = 2e5;
|
|
2750
2768
|
function clampCacheSize(entries) {
|
|
2751
|
-
return Math.max(
|
|
2769
|
+
return Math.max(TOKEN_CACHE_SIZE_FLOOR, Math.min(entries, TOKEN_CACHE_SIZE_CEILING));
|
|
2752
2770
|
}
|
|
2753
2771
|
function computeDefaultCacheSize() {
|
|
2754
2772
|
try {
|
|
2755
2773
|
if (typeof process !== "undefined" && typeof process.versions?.node === "string" && typeof window === "undefined") {
|
|
2756
2774
|
const constrainedMemory = typeof process.constrainedMemory === "function" ? process.constrainedMemory() : 0;
|
|
2757
2775
|
if (constrainedMemory > 0) {
|
|
2758
|
-
|
|
2776
|
+
const budget = constrainedMemory * CONSTRAINED_MEMORY_TOKEN_CACHE_FRACTION;
|
|
2777
|
+
return clampCacheSize(Math.floor(budget / TOKEN_CACHE_BYTES_PER_ENTRY));
|
|
2759
2778
|
}
|
|
2760
|
-
return clampCacheSize(
|
|
2779
|
+
return clampCacheSize(NODE_TOKEN_CACHE_ENTRIES);
|
|
2761
2780
|
}
|
|
2762
2781
|
if (typeof navigator !== "undefined") {
|
|
2763
2782
|
const mem = navigator.deviceMemory;
|
|
2764
2783
|
if (typeof mem === "number" && mem > 0) {
|
|
2765
2784
|
let entries;
|
|
2766
|
-
if (mem <=
|
|
2767
|
-
else if (mem <=
|
|
2768
|
-
else entries =
|
|
2785
|
+
if (mem <= SMALL_DEVICE_MEMORY_GB) entries = SMALL_DEVICE_TOKEN_CACHE_ENTRIES;
|
|
2786
|
+
else if (mem <= MEDIUM_DEVICE_MEMORY_GB) entries = MEDIUM_DEVICE_TOKEN_CACHE_ENTRIES;
|
|
2787
|
+
else entries = LARGE_DEVICE_TOKEN_CACHE_ENTRIES;
|
|
2769
2788
|
return clampCacheSize(entries);
|
|
2770
2789
|
}
|
|
2771
2790
|
}
|
|
2772
2791
|
} catch {
|
|
2773
|
-
return clampCacheSize(
|
|
2792
|
+
return clampCacheSize(UNKNOWN_MEMORY_TOKEN_CACHE_ENTRIES);
|
|
2774
2793
|
}
|
|
2775
|
-
return clampCacheSize(
|
|
2794
|
+
return clampCacheSize(UNKNOWN_MEMORY_TOKEN_CACHE_ENTRIES);
|
|
2776
2795
|
}
|
|
2777
2796
|
var normalizationCache = /* @__PURE__ */ new Map();
|
|
2778
2797
|
var normalizationCacheSize = 0;
|
|
@@ -2800,7 +2819,7 @@ function configureNormalizationCache(maxSize) {
|
|
|
2800
2819
|
}
|
|
2801
2820
|
);
|
|
2802
2821
|
}
|
|
2803
|
-
maxCacheSize = Math.max(
|
|
2822
|
+
maxCacheSize = Math.max(TOKEN_CACHE_SIZE_FLOOR, Math.min(Math.floor(maxSize), TOKEN_CACHE_SIZE_CEILING));
|
|
2804
2823
|
if (normalizationCacheSize > maxCacheSize) {
|
|
2805
2824
|
evictOldestEntries(normalizationCacheSize - maxCacheSize);
|
|
2806
2825
|
}
|
|
@@ -3013,7 +3032,6 @@ function expandNgrams(part, size, out) {
|
|
|
3013
3032
|
|
|
3014
3033
|
// src/core/tokenizer/tokenize.ts
|
|
3015
3034
|
var DEFAULT_SPLIT_PATTERN = /[^\p{L}\p{M}\p{N}_'-]+/u;
|
|
3016
|
-
var DEFAULT_MIN_TOKEN_LENGTH = 1;
|
|
3017
3035
|
function resolveStopWords(language, override) {
|
|
3018
3036
|
if (!override) return language.stopWords;
|
|
3019
3037
|
if (override instanceof Set) return override;
|
|
@@ -3998,14 +4016,27 @@ function partitionFilterMatches(state, filters, schema) {
|
|
|
3998
4016
|
};
|
|
3999
4017
|
}
|
|
4000
4018
|
|
|
4019
|
+
// src/core/partition/posting-columns.ts
|
|
4020
|
+
function postingColumns(list) {
|
|
4021
|
+
const deletedDocs = list.deletedDocs;
|
|
4022
|
+
return {
|
|
4023
|
+
docIds: list.docIds,
|
|
4024
|
+
termFrequencies: list.termFrequencies,
|
|
4025
|
+
fieldNameIndices: list.fieldNameIndices,
|
|
4026
|
+
deletedDocs,
|
|
4027
|
+
hasDeleted: deletedDocs.size > 0,
|
|
4028
|
+
count: list.length
|
|
4029
|
+
};
|
|
4030
|
+
}
|
|
4031
|
+
|
|
4001
4032
|
// src/core/partition/matches.ts
|
|
4002
4033
|
function markPostingList(matched, list, fieldNames, fields, filterBitset) {
|
|
4003
|
-
const hasDeleted = list
|
|
4004
|
-
for (let pi = 0; pi <
|
|
4005
|
-
const internalId =
|
|
4006
|
-
if (hasDeleted &&
|
|
4034
|
+
const { docIds, fieldNameIndices, deletedDocs, hasDeleted, count } = postingColumns(list);
|
|
4035
|
+
for (let pi = 0; pi < count; pi++) {
|
|
4036
|
+
const internalId = docIds[pi];
|
|
4037
|
+
if (hasDeleted && deletedDocs.has(internalId)) continue;
|
|
4007
4038
|
if (filterBitset && !bitsetHas(filterBitset, internalId)) continue;
|
|
4008
|
-
if (fields && !fields.includes(fieldNames[
|
|
4039
|
+
if (fields && !fields.includes(fieldNames[fieldNameIndices[pi]])) continue;
|
|
4009
4040
|
bitsetSet(matched, internalId);
|
|
4010
4041
|
}
|
|
4011
4042
|
}
|
|
@@ -4076,6 +4107,12 @@ function searchFulltextMatches(state, params) {
|
|
|
4076
4107
|
};
|
|
4077
4108
|
}
|
|
4078
4109
|
|
|
4110
|
+
// src/core/partition/constants.ts
|
|
4111
|
+
var TARGET_BLOCK_ENTRIES = 128;
|
|
4112
|
+
var SCORE_BUFFER_INITIAL_TOUCHED_CAPACITY = 1024;
|
|
4113
|
+
var SORT_COLUMN_MINIMUM_REBUILD_THRESHOLD = 1024;
|
|
4114
|
+
var SORT_COLUMN_REBUILD_FRACTION_SHIFT = 2;
|
|
4115
|
+
|
|
4079
4116
|
// src/core/partition/sort-columns/order.ts
|
|
4080
4117
|
var MISSING_RANK = -1;
|
|
4081
4118
|
var BYTES_PER_RANK = 4;
|
|
@@ -4301,8 +4338,6 @@ function createValueStore(initialKind) {
|
|
|
4301
4338
|
}
|
|
4302
4339
|
|
|
4303
4340
|
// src/core/partition/sort-columns/index.ts
|
|
4304
|
-
var MINIMUM_REBUILD_THRESHOLD = 1024;
|
|
4305
|
-
var REBUILD_FRACTION_SHIFT = 2;
|
|
4306
4341
|
function liveInternalIds(docStore) {
|
|
4307
4342
|
const ids = [];
|
|
4308
4343
|
for (const internalId of docStore.allInternalIds()) ids.push(internalId);
|
|
@@ -4312,8 +4347,8 @@ function createSortColumnSet(docStore) {
|
|
|
4312
4347
|
const columns = /* @__PURE__ */ new Map();
|
|
4313
4348
|
function rebuildThreshold() {
|
|
4314
4349
|
const count = docStore.count();
|
|
4315
|
-
const fraction = count >>
|
|
4316
|
-
return fraction >
|
|
4350
|
+
const fraction = count >> SORT_COLUMN_REBUILD_FRACTION_SHIFT;
|
|
4351
|
+
return fraction > SORT_COLUMN_MINIMUM_REBUILD_THRESHOLD ? fraction : SORT_COLUMN_MINIMUM_REBUILD_THRESHOLD;
|
|
4317
4352
|
}
|
|
4318
4353
|
function rebuild(entry) {
|
|
4319
4354
|
entry.order = buildOrder(entry.store, docStore.allInternalIds(), docStore.internalIdCapacity());
|
|
@@ -4942,13 +4977,12 @@ function sortSelection(heap) {
|
|
|
4942
4977
|
}
|
|
4943
4978
|
|
|
4944
4979
|
// src/core/partition/score-buffer.ts
|
|
4945
|
-
var INITIAL_TOUCHED_CAPACITY = 1024;
|
|
4946
4980
|
var MAX_GENERATION = 2147483647;
|
|
4947
4981
|
function createScoreBuffer(capacity) {
|
|
4948
4982
|
return {
|
|
4949
4983
|
scores: new Float64Array(capacity),
|
|
4950
4984
|
stamps: new Int32Array(capacity),
|
|
4951
|
-
touched: new Int32Array(Math.max(1, Math.min(capacity,
|
|
4985
|
+
touched: new Int32Array(Math.max(1, Math.min(capacity, SCORE_BUFFER_INITIAL_TOUCHED_CAPACITY))),
|
|
4952
4986
|
touchedCount: 0,
|
|
4953
4987
|
generation: 0
|
|
4954
4988
|
};
|
|
@@ -5033,7 +5067,6 @@ function topKFromBuffer(buffer, k, resolver, components) {
|
|
|
5033
5067
|
}
|
|
5034
5068
|
|
|
5035
5069
|
// src/core/partition/block-bounds.ts
|
|
5036
|
-
var TARGET_BLOCK_ENTRIES = 128;
|
|
5037
5070
|
var ABSENT_FIELD_LENGTH_BOUND = 0;
|
|
5038
5071
|
var boundsByList = /* @__PURE__ */ new WeakMap();
|
|
5039
5072
|
function fieldLengthBound(columns, fieldIndex, internalId) {
|
|
@@ -5142,12 +5175,27 @@ function bestSearchable(searchable, values) {
|
|
|
5142
5175
|
}
|
|
5143
5176
|
return best;
|
|
5144
5177
|
}
|
|
5178
|
+
function prunableSingleTermList(params, index) {
|
|
5179
|
+
if (params.queryTokens.length !== 1) return null;
|
|
5180
|
+
if (params.prefixExpansion !== void 0) return null;
|
|
5181
|
+
if (params.exact !== true && (params.tolerance ?? 0) !== 0) return null;
|
|
5182
|
+
if (params.termMatch !== void 0 && params.termMatch !== "any") return null;
|
|
5183
|
+
if (params.collectComponents !== false) return null;
|
|
5184
|
+
if (params.collectMatchedSet !== void 0) return null;
|
|
5185
|
+
if (params.maxResults === void 0) return null;
|
|
5186
|
+
if (params.fields !== void 0) return null;
|
|
5187
|
+
if (params.filterBitset !== void 0) return null;
|
|
5188
|
+
if (!bm25PruningSound(params.bm25Params)) return null;
|
|
5189
|
+
const list = index.lookup(params.queryTokens[0].token);
|
|
5190
|
+
if (list === void 0) return null;
|
|
5191
|
+
if (!list.ordered) return null;
|
|
5192
|
+
return list;
|
|
5193
|
+
}
|
|
5145
5194
|
function singleTermTopK(request) {
|
|
5146
5195
|
const { list, docFrequency, totalDocs, bm25Params, limit, resolver } = request;
|
|
5147
5196
|
const { fieldSearchable, fieldBoosts, fieldAvgLengths, fieldLengthColumns } = request;
|
|
5148
5197
|
const wanted = Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 0;
|
|
5149
|
-
const deleted = list
|
|
5150
|
-
const hasDeleted = deleted.size > 0;
|
|
5198
|
+
const { docIds, termFrequencies, fieldNameIndices, deletedDocs: deleted, hasDeleted } = postingColumns(list);
|
|
5151
5199
|
const bounds = blockBoundsFor(list, fieldLengthColumns);
|
|
5152
5200
|
const maxBoost = bestSearchable(fieldSearchable, fieldBoosts);
|
|
5153
5201
|
const maxAverageLength = bestSearchable(fieldSearchable, fieldAvgLengths);
|
|
@@ -5174,19 +5222,19 @@ function singleTermTopK(request) {
|
|
|
5174
5222
|
}
|
|
5175
5223
|
let entry = start;
|
|
5176
5224
|
while (entry < end) {
|
|
5177
|
-
const internalId =
|
|
5225
|
+
const internalId = docIds[entry];
|
|
5178
5226
|
if (hasDeleted && deleted.has(internalId)) {
|
|
5179
|
-
while (entry < end &&
|
|
5227
|
+
while (entry < end && docIds[entry] === internalId) entry++;
|
|
5180
5228
|
continue;
|
|
5181
5229
|
}
|
|
5182
5230
|
let score = 0;
|
|
5183
5231
|
let scored2 = false;
|
|
5184
|
-
while (entry < end &&
|
|
5185
|
-
const fieldIndex =
|
|
5232
|
+
while (entry < end && docIds[entry] === internalId) {
|
|
5233
|
+
const fieldIndex = fieldNameIndices[entry];
|
|
5186
5234
|
if (fieldSearchable[fieldIndex] === 1) {
|
|
5187
5235
|
const fieldLength = fieldLengthOf(fieldLengthColumns, fieldIndex, internalId, fieldAvgLengths[fieldIndex]);
|
|
5188
5236
|
score += computeBM25(
|
|
5189
|
-
|
|
5237
|
+
termFrequencies[entry],
|
|
5190
5238
|
docFrequency,
|
|
5191
5239
|
totalDocs,
|
|
5192
5240
|
fieldLength,
|
|
@@ -5238,21 +5286,10 @@ function singleTermTopK(request) {
|
|
|
5238
5286
|
function globalDocFreqFor(docFreqs, term, fallback) {
|
|
5239
5287
|
return Object.hasOwn(docFreqs, term) ? docFreqs[term] : fallback;
|
|
5240
5288
|
}
|
|
5241
|
-
function
|
|
5242
|
-
if (
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
if (params.termMatch !== void 0 && params.termMatch !== "any") return null;
|
|
5246
|
-
if (params.collectComponents !== false) return null;
|
|
5247
|
-
if (params.collectMatchedSet !== void 0) return null;
|
|
5248
|
-
if (params.maxResults === void 0) return null;
|
|
5249
|
-
if (params.fields !== void 0) return null;
|
|
5250
|
-
if (params.filterBitset !== void 0) return null;
|
|
5251
|
-
if (!bm25PruningSound(params.bm25Params)) return null;
|
|
5252
|
-
const list = index.lookup(params.queryTokens[0].token);
|
|
5253
|
-
if (list === void 0) return null;
|
|
5254
|
-
if (!list.ordered) return null;
|
|
5255
|
-
return list;
|
|
5289
|
+
function matchesFor(index, token, exact, tolerance, prefixLength) {
|
|
5290
|
+
if (!exact) return index.fuzzyLookup(token, tolerance, prefixLength);
|
|
5291
|
+
const postingList = index.lookup(token);
|
|
5292
|
+
return postingList ? [{ token, postingList }] : [];
|
|
5256
5293
|
}
|
|
5257
5294
|
function searchFulltext(state, params) {
|
|
5258
5295
|
const {
|
|
@@ -5333,17 +5370,18 @@ function searchFulltext(state, params) {
|
|
|
5333
5370
|
const best = /* @__PURE__ */ new Map();
|
|
5334
5371
|
for (const match of matches) {
|
|
5335
5372
|
const perTerm = /* @__PURE__ */ new Map();
|
|
5336
|
-
const
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5373
|
+
const { docIds, termFrequencies, fieldNameIndices, deletedDocs, hasDeleted, count } = postingColumns(
|
|
5374
|
+
match.postingList
|
|
5375
|
+
);
|
|
5376
|
+
for (let pi = 0; pi < count; pi++) {
|
|
5377
|
+
const internalId = docIds[pi];
|
|
5378
|
+
if (hasDeleted && deletedDocs.has(internalId)) continue;
|
|
5341
5379
|
if (filterBitset && !bitsetHas(filterBitset, internalId)) continue;
|
|
5342
|
-
const fieldIndex =
|
|
5380
|
+
const fieldIndex = fieldNameIndices[pi];
|
|
5343
5381
|
loadFieldMeta(fieldIndex);
|
|
5344
5382
|
if (fieldSearchable[fieldIndex] === 0) continue;
|
|
5345
5383
|
const fieldName = fieldNames[fieldIndex];
|
|
5346
|
-
const termFrequency =
|
|
5384
|
+
const termFrequency = termFrequencies[pi];
|
|
5347
5385
|
const fieldBoost = fieldBoosts[fieldIndex];
|
|
5348
5386
|
const avgLen = fieldAvgLengths[fieldIndex];
|
|
5349
5387
|
const actualFieldLength = resolveFieldLength(internalId, fieldIndex, avgLen);
|
|
@@ -5415,10 +5453,7 @@ function searchFulltext(state, params) {
|
|
|
5415
5453
|
resolved.push({ token: qt.token, matches: [], totalPostings: totalPostings2, isPrefix: true });
|
|
5416
5454
|
continue;
|
|
5417
5455
|
}
|
|
5418
|
-
const rawMatches = exact
|
|
5419
|
-
const postingList = state.invertedIdx.lookup(qt.token);
|
|
5420
|
-
return postingList ? [{ token: qt.token, postingList }] : [];
|
|
5421
|
-
})() : state.invertedIdx.fuzzyLookup(qt.token, tolerance, prefixLength);
|
|
5456
|
+
const rawMatches = matchesFor(state.invertedIdx, qt.token, exact, tolerance, prefixLength);
|
|
5422
5457
|
let totalPostings = 0;
|
|
5423
5458
|
const matches = [];
|
|
5424
5459
|
for (const m of rawMatches) {
|
|
@@ -5440,17 +5475,18 @@ function searchFulltext(state, params) {
|
|
|
5440
5475
|
continue;
|
|
5441
5476
|
}
|
|
5442
5477
|
for (const match of resolved[tokenIndex].matches) {
|
|
5443
|
-
const
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5478
|
+
const { docIds, termFrequencies, fieldNameIndices, deletedDocs, hasDeleted, count } = postingColumns(
|
|
5479
|
+
match.postingList
|
|
5480
|
+
);
|
|
5481
|
+
for (let pi = 0; pi < count; pi++) {
|
|
5482
|
+
const internalId = docIds[pi];
|
|
5483
|
+
if (hasDeleted && deletedDocs.has(internalId)) continue;
|
|
5448
5484
|
if (filterBitset && !bitsetHas(filterBitset, internalId)) continue;
|
|
5449
5485
|
if (tokenIndex > 0 && !hasScore(scoreBuffer, internalId)) continue;
|
|
5450
|
-
const fieldIndex =
|
|
5486
|
+
const fieldIndex = fieldNameIndices[pi];
|
|
5451
5487
|
loadFieldMeta(fieldIndex);
|
|
5452
5488
|
if (fieldSearchable[fieldIndex] === 0) continue;
|
|
5453
|
-
const termFrequency =
|
|
5489
|
+
const termFrequency = termFrequencies[pi];
|
|
5454
5490
|
const fieldBoost = fieldBoosts[fieldIndex];
|
|
5455
5491
|
const avgLen = fieldAvgLengths[fieldIndex];
|
|
5456
5492
|
const actualFieldLength = resolveFieldLength(internalId, fieldIndex, avgLen);
|
|
@@ -5483,23 +5519,21 @@ function searchFulltext(state, params) {
|
|
|
5483
5519
|
}
|
|
5484
5520
|
continue;
|
|
5485
5521
|
}
|
|
5486
|
-
const matchingPostings = exact
|
|
5487
|
-
const postingList = state.invertedIdx.lookup(qt.token);
|
|
5488
|
-
return postingList ? [{ token: qt.token, postingList }] : [];
|
|
5489
|
-
})() : state.invertedIdx.fuzzyLookup(qt.token, tolerance, prefixLength);
|
|
5522
|
+
const matchingPostings = matchesFor(state.invertedIdx, qt.token, exact, tolerance, prefixLength);
|
|
5490
5523
|
for (const match of matchingPostings) {
|
|
5491
5524
|
const docFreq = globalStats ? globalDocFreqFor(globalDocFreqs, match.token, match.postingList.docIdSet.size) : match.postingList.docIdSet.size;
|
|
5492
5525
|
const idf = computeIDF(docFreq, totalDocs);
|
|
5493
|
-
const
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5526
|
+
const { docIds, termFrequencies, fieldNameIndices, deletedDocs, hasDeleted, count } = postingColumns(
|
|
5527
|
+
match.postingList
|
|
5528
|
+
);
|
|
5529
|
+
for (let pi = 0; pi < count; pi++) {
|
|
5530
|
+
const internalId = docIds[pi];
|
|
5531
|
+
if (hasDeleted && deletedDocs.has(internalId)) continue;
|
|
5498
5532
|
if (filterBitset && !bitsetHas(filterBitset, internalId)) continue;
|
|
5499
|
-
const fieldIndex =
|
|
5533
|
+
const fieldIndex = fieldNameIndices[pi];
|
|
5500
5534
|
loadFieldMeta(fieldIndex);
|
|
5501
5535
|
if (fieldSearchable[fieldIndex] === 0) continue;
|
|
5502
|
-
const termFrequency =
|
|
5536
|
+
const termFrequency = termFrequencies[pi];
|
|
5503
5537
|
const fieldBoost = fieldBoosts[fieldIndex];
|
|
5504
5538
|
const avgLen = fieldAvgLengths[fieldIndex];
|
|
5505
5539
|
const actualFieldLength = resolveFieldLength(internalId, fieldIndex, avgLen);
|
|
@@ -7147,6 +7181,9 @@ function createFrozenTombstones() {
|
|
|
7147
7181
|
removed.add(internalId);
|
|
7148
7182
|
revision++;
|
|
7149
7183
|
return true;
|
|
7184
|
+
},
|
|
7185
|
+
values() {
|
|
7186
|
+
return removed.values();
|
|
7150
7187
|
}
|
|
7151
7188
|
};
|
|
7152
7189
|
}
|
|
@@ -7270,7 +7307,7 @@ function buildGeoReaders(entries) {
|
|
|
7270
7307
|
}
|
|
7271
7308
|
return readers;
|
|
7272
7309
|
}
|
|
7273
|
-
function assembleFrozenSegment(segmentId, source, documentSource) {
|
|
7310
|
+
function assembleFrozenSegment(segmentId, source, documentSource, sharedSnapshot) {
|
|
7274
7311
|
const tombstones = createFrozenTombstones();
|
|
7275
7312
|
const postingViews = createFrozenPostingViews(source, tombstones);
|
|
7276
7313
|
const lengthColumns = /* @__PURE__ */ new Map();
|
|
@@ -7291,6 +7328,7 @@ function assembleFrozenSegment(segmentId, source, documentSource) {
|
|
|
7291
7328
|
const segment = {
|
|
7292
7329
|
segmentId,
|
|
7293
7330
|
documentSource,
|
|
7331
|
+
sharedSnapshot,
|
|
7294
7332
|
invertedIdx: createFrozenInvertedReader(source.tokenTable, postingViews),
|
|
7295
7333
|
docStore,
|
|
7296
7334
|
stats: buildStatsView(source),
|
|
@@ -7321,6 +7359,11 @@ function assembleFrozenSegment(segmentId, source, documentSource) {
|
|
|
7321
7359
|
segment.scoreBuffer = null;
|
|
7322
7360
|
}
|
|
7323
7361
|
return added;
|
|
7362
|
+
},
|
|
7363
|
+
tombstonedDocIds() {
|
|
7364
|
+
const docIds = [];
|
|
7365
|
+
for (const ordinal of tombstones.values()) docIds.push(source.idTable.idAt(ordinal));
|
|
7366
|
+
return docIds;
|
|
7324
7367
|
}
|
|
7325
7368
|
};
|
|
7326
7369
|
return segment;
|
|
@@ -7334,7 +7377,8 @@ function createFrozenSegment(payload, documents, segmentId) {
|
|
|
7334
7377
|
idTable: buildExternalIdTable(payload.docIds),
|
|
7335
7378
|
docFrequencies: () => payload.docFrequencies
|
|
7336
7379
|
},
|
|
7337
|
-
wrapDocumentArray(documents)
|
|
7380
|
+
wrapDocumentArray(documents),
|
|
7381
|
+
null
|
|
7338
7382
|
);
|
|
7339
7383
|
}
|
|
7340
7384
|
function createSharedFrozenSegment(snapshot) {
|
|
@@ -7353,7 +7397,8 @@ function createSharedFrozenSegment(snapshot) {
|
|
|
7353
7397
|
return frequencies;
|
|
7354
7398
|
}
|
|
7355
7399
|
},
|
|
7356
|
-
wrapEncodedDocumentTable(snapshot.documentTable)
|
|
7400
|
+
wrapEncodedDocumentTable(snapshot.documentTable),
|
|
7401
|
+
snapshot
|
|
7357
7402
|
);
|
|
7358
7403
|
}
|
|
7359
7404
|
|
|
@@ -7395,6 +7440,15 @@ function buildCompactedSegmentPayload(segments) {
|
|
|
7395
7440
|
}
|
|
7396
7441
|
return { payload: scratch.encodeSegment(), documents };
|
|
7397
7442
|
}
|
|
7443
|
+
function freezeLiveTailInto(live, liveState, frozen, freeze) {
|
|
7444
|
+
if (live.count() === 0) return null;
|
|
7445
|
+
const payload = live.encodeSegment();
|
|
7446
|
+
const segment = freeze(payload, survivorDocumentsOf(liveState, payload));
|
|
7447
|
+
if (segment === null) return null;
|
|
7448
|
+
live.clear();
|
|
7449
|
+
frozen.push(segment);
|
|
7450
|
+
return segment;
|
|
7451
|
+
}
|
|
7398
7452
|
function swapFrozenSegmentList(frozen, dropSegmentIds, replacement, partitionId) {
|
|
7399
7453
|
const dropped = resolveFrozenSegments(frozen, dropSegmentIds, partitionId);
|
|
7400
7454
|
const dropSet = new Set(dropSegmentIds);
|
|
@@ -7434,11 +7488,15 @@ function subBitsetView(composite, layout, subIndex) {
|
|
|
7434
7488
|
const endWord = subIndex + 1 < layout.bases.length ? layout.bases[subIndex + 1] >> 5 : Math.ceil(layout.totalCapacity / WORD_BITS);
|
|
7435
7489
|
return composite.subarray(startWord, endWord);
|
|
7436
7490
|
}
|
|
7491
|
+
function placeSubBitset(composite, layout, subIndex, subBits) {
|
|
7492
|
+
const words = subBitsetView(composite, layout, subIndex).length;
|
|
7493
|
+
if (words === 0) return;
|
|
7494
|
+
composite.set(subBits.length > words ? subBits.subarray(0, words) : subBits, layout.bases[subIndex] >> 5);
|
|
7495
|
+
}
|
|
7437
7496
|
function compositeFiltersBitset(subs, layout, filters, schema) {
|
|
7438
7497
|
const composite = new Uint32Array(Math.ceil(layout.totalCapacity / WORD_BITS));
|
|
7439
7498
|
for (let i = 0; i < subs.length; i++) {
|
|
7440
|
-
|
|
7441
|
-
composite.set(subBits, layout.bases[i] >> 5);
|
|
7499
|
+
placeSubBitset(composite, layout, i, applyPartitionFiltersBitset(subs[i], filters, schema));
|
|
7442
7500
|
}
|
|
7443
7501
|
return composite;
|
|
7444
7502
|
}
|
|
@@ -7700,10 +7758,30 @@ function subParams(params, layout, subIndex, globalStats) {
|
|
|
7700
7758
|
filterBitset: params.filterBitset === void 0 ? void 0 : subBitsetView(params.filterBitset, layout, subIndex)
|
|
7701
7759
|
};
|
|
7702
7760
|
}
|
|
7761
|
+
function onlyPopulatedSub(subs) {
|
|
7762
|
+
let found = -1;
|
|
7763
|
+
for (let i = 0; i < subs.length; i++) {
|
|
7764
|
+
if (subs[i].stats.totalDocuments === 0) continue;
|
|
7765
|
+
if (found !== -1) return -1;
|
|
7766
|
+
found = i;
|
|
7767
|
+
}
|
|
7768
|
+
return found;
|
|
7769
|
+
}
|
|
7770
|
+
function searchSingleSub(subs, layout, params, index) {
|
|
7771
|
+
const result = searchFulltext(subs[index], subParams(params, layout, index, params.globalStats));
|
|
7772
|
+
if (result.matchedOrdinalBitset === void 0) return result;
|
|
7773
|
+
const matchedOrdinalBitset = createBitSet(layout.totalCapacity);
|
|
7774
|
+
placeSubBitset(matchedOrdinalBitset, layout, index, result.matchedOrdinalBitset);
|
|
7775
|
+
return { ...result, matchedOrdinalBitset };
|
|
7776
|
+
}
|
|
7703
7777
|
function compositeSearchFulltext(subs, layout, params) {
|
|
7704
7778
|
if (params.queryTokens.length === 0) {
|
|
7705
7779
|
return { scored: [], totalMatched: 0 };
|
|
7706
7780
|
}
|
|
7781
|
+
const single = onlyPopulatedSub(subs);
|
|
7782
|
+
if (single !== -1) {
|
|
7783
|
+
return searchSingleSub(subs, layout, params, single);
|
|
7784
|
+
}
|
|
7707
7785
|
const globalStats = compositeQueryStats(subs, params);
|
|
7708
7786
|
const results = subs.map((sub, index) => searchFulltext(sub, subParams(params, layout, index, globalStats)));
|
|
7709
7787
|
const scored = kWayMerge(results.map((result) => result.scored));
|
|
@@ -7721,7 +7799,7 @@ function compositeSearchFulltext(subs, layout, params) {
|
|
|
7721
7799
|
const matchedOrdinalBitset = createBitSet(layout.totalCapacity);
|
|
7722
7800
|
for (let i = 0; i < results.length; i++) {
|
|
7723
7801
|
const subBitset = results[i].matchedOrdinalBitset;
|
|
7724
|
-
if (subBitset !== void 0) matchedOrdinalBitset
|
|
7802
|
+
if (subBitset !== void 0) placeSubBitset(matchedOrdinalBitset, layout, i, subBitset);
|
|
7725
7803
|
}
|
|
7726
7804
|
return { scored, totalMatched, matchedOrdinalBitset };
|
|
7727
7805
|
}
|
|
@@ -7765,7 +7843,7 @@ function compositeSearchMatches(subs, layout, params) {
|
|
|
7765
7843
|
ordinalBitset() {
|
|
7766
7844
|
const combined = createBitSet(layout.totalCapacity);
|
|
7767
7845
|
for (let i = 0; i < subMatches.length; i++) {
|
|
7768
|
-
combined
|
|
7846
|
+
placeSubBitset(combined, layout, i, subMatches[i].ordinalBitset());
|
|
7769
7847
|
}
|
|
7770
7848
|
return combined;
|
|
7771
7849
|
}
|
|
@@ -7848,17 +7926,6 @@ function compositeExpandTermPrefix(subs, surfacePrefix, stemmedToken, maxExpansi
|
|
|
7848
7926
|
function isCompositePartition(partition) {
|
|
7849
7927
|
return "attachFrozenSegment" in partition;
|
|
7850
7928
|
}
|
|
7851
|
-
function survivorDocuments(sub, payload) {
|
|
7852
|
-
return payload.docIds.map((docId) => {
|
|
7853
|
-
const stored = sub.docStore.get(docId);
|
|
7854
|
-
if (stored === void 0) {
|
|
7855
|
-
throw new NarsilError(ErrorCodes.PARTITION_CORRUPTED, `Document "${docId}" vanished while composing a segment`, {
|
|
7856
|
-
docId
|
|
7857
|
-
});
|
|
7858
|
-
}
|
|
7859
|
-
return stored.fields;
|
|
7860
|
-
});
|
|
7861
|
-
}
|
|
7862
7929
|
function createCompositePartition(partitionId, trackPositions = true, existingLive) {
|
|
7863
7930
|
const live = existingLive ?? createPartitionIndex(partitionId, trackPositions);
|
|
7864
7931
|
const liveState = partitionStateOf(live);
|
|
@@ -7881,7 +7948,7 @@ function createCompositePartition(partitionId, trackPositions = true, existingLi
|
|
|
7881
7948
|
for (const sub of subs()) {
|
|
7882
7949
|
const payload = encodeSegmentState(sub);
|
|
7883
7950
|
if (payload.documentCount === 0) continue;
|
|
7884
|
-
scratch.mergeSegmentPayload(payload,
|
|
7951
|
+
scratch.mergeSegmentPayload(payload, survivorDocumentsOf(sub, payload));
|
|
7885
7952
|
}
|
|
7886
7953
|
return scratch;
|
|
7887
7954
|
}
|
|
@@ -7917,6 +7984,16 @@ function createCompositePartition(partitionId, trackPositions = true, existingLi
|
|
|
7917
7984
|
swapFrozenSegmentList(frozen, dropSegmentIds, replacement, partitionId);
|
|
7918
7985
|
invalidateDocFrequencies();
|
|
7919
7986
|
},
|
|
7987
|
+
freezeLiveTail(freeze) {
|
|
7988
|
+
const segment = freezeLiveTailInto(live, liveState, frozen, freeze);
|
|
7989
|
+
if (segment !== null) invalidateDocFrequencies();
|
|
7990
|
+
return segment;
|
|
7991
|
+
},
|
|
7992
|
+
replaceLiveTail(segment) {
|
|
7993
|
+
live.clear();
|
|
7994
|
+
frozen.push(segment);
|
|
7995
|
+
invalidateDocFrequencies();
|
|
7996
|
+
},
|
|
7920
7997
|
appendFrozenSegment(payload, documents) {
|
|
7921
7998
|
for (const docId of payload.docIds) {
|
|
7922
7999
|
if (live.has(docId) || frozenOwner(docId) !== void 0) {
|
|
@@ -7961,7 +8038,7 @@ function createCompositePartition(partitionId, trackPositions = true, existingLi
|
|
|
7961
8038
|
for (const segment of frozen) {
|
|
7962
8039
|
const payload = encodeSegmentState(segment);
|
|
7963
8040
|
if (payload.documentCount === 0) continue;
|
|
7964
|
-
live.mergeSegmentPayload(payload,
|
|
8041
|
+
live.mergeSegmentPayload(payload, survivorDocumentsOf(segment, payload));
|
|
7965
8042
|
}
|
|
7966
8043
|
frozen.length = 0;
|
|
7967
8044
|
}
|
|
@@ -8304,11 +8381,6 @@ function applySorting(hits, sort, sortKeyOf) {
|
|
|
8304
8381
|
|
|
8305
8382
|
// src/search/cursor.ts
|
|
8306
8383
|
var CURSOR_VERSION = 3;
|
|
8307
|
-
var MAX_CURSOR_LENGTH = 40960;
|
|
8308
|
-
var MAX_SORT_FIELDS = 8;
|
|
8309
|
-
var MAX_SORT_FIELD_NAME_LENGTH = 255;
|
|
8310
|
-
var MAX_ANCHOR_CODE_POINTS = 512;
|
|
8311
|
-
var MAX_SORT_VALUE_CODE_POINTS = 512;
|
|
8312
8384
|
function invalidCursor(cursor, reason) {
|
|
8313
8385
|
const shown = cursor.length > 100 ? `${cursor.slice(0, 100)}...` : cursor;
|
|
8314
8386
|
return new NarsilError(ErrorCodes.SEARCH_INVALID_CURSOR, `Failed to decode cursor: ${reason}`, { cursor: shown });
|
|
@@ -8376,7 +8448,7 @@ function decodeSortKey(value, cursor) {
|
|
|
8376
8448
|
continue;
|
|
8377
8449
|
}
|
|
8378
8450
|
if (typeof entry === "string") {
|
|
8379
|
-
if (exceedsCodePoints(entry,
|
|
8451
|
+
if (exceedsCodePoints(entry, SORT_VALUE_MAX_CODE_POINTS)) {
|
|
8380
8452
|
throw invalidCursor(cursor, '"k" holds an oversized sort value');
|
|
8381
8453
|
}
|
|
8382
8454
|
key.push(entry);
|
|
@@ -8409,7 +8481,7 @@ function decodePageCursor(cursor) {
|
|
|
8409
8481
|
throw invalidCursor(cursor, '"q" must be 8 lowercase hex digits');
|
|
8410
8482
|
}
|
|
8411
8483
|
if (typeof a !== "string" || a.length === 0) throw invalidCursor(cursor, '"a" must be a non-empty string');
|
|
8412
|
-
if (exceedsCodePoints(a,
|
|
8484
|
+
if (exceedsCodePoints(a, MAX_CURSOR_ANCHOR_CODE_POINTS)) {
|
|
8413
8485
|
throw invalidCursor(cursor, '"a" is too long to be a document id');
|
|
8414
8486
|
}
|
|
8415
8487
|
if (s !== void 0 && (typeof s !== "number" || !Number.isFinite(s))) {
|
|
@@ -8451,8 +8523,6 @@ function requireMatchingCursor(cursor, encoded, signature, scoreAnchored, bindin
|
|
|
8451
8523
|
}
|
|
8452
8524
|
|
|
8453
8525
|
// src/search/pagination.ts
|
|
8454
|
-
var RESULT_WINDOW = 1e4;
|
|
8455
|
-
var DEFAULT_PAGE_SIZE = 10;
|
|
8456
8526
|
function clampRowCount(value, fallback) {
|
|
8457
8527
|
if (value === void 0 || !Number.isFinite(value)) return fallback;
|
|
8458
8528
|
return Math.max(0, Math.floor(value));
|
|
@@ -8524,7 +8594,6 @@ function applyPagination(results, limit, offset, binding, cursor, sort, pinnedId
|
|
|
8524
8594
|
}
|
|
8525
8595
|
|
|
8526
8596
|
// src/search/fulltext.ts
|
|
8527
|
-
var PREFIX_MAX_EXPANSIONS = 50;
|
|
8528
8597
|
function resolvePrefixExpansion(partition, params, language, options, queryTokens, lastToken) {
|
|
8529
8598
|
const term = params.term;
|
|
8530
8599
|
if (term === void 0) return void 0;
|
|
@@ -9171,6 +9240,14 @@ function createPartitionManager(indexName, config, language, router, initialPart
|
|
|
9171
9240
|
if (docId !== void 0) docPartitionMap.set(docId, partitionId);
|
|
9172
9241
|
}
|
|
9173
9242
|
},
|
|
9243
|
+
freezeLiveTail(partitionId, freeze) {
|
|
9244
|
+
validatePartitionId(partitionId);
|
|
9245
|
+
return asCompositePartition(partitionId).freezeLiveTail(freeze);
|
|
9246
|
+
},
|
|
9247
|
+
replaceLiveTail(partitionId, segment) {
|
|
9248
|
+
validatePartitionId(partitionId);
|
|
9249
|
+
asCompositePartition(partitionId).replaceLiveTail(segment);
|
|
9250
|
+
},
|
|
9174
9251
|
deserializePartition(partitionId, data) {
|
|
9175
9252
|
validatePartitionId(partitionId);
|
|
9176
9253
|
partitions[partitionId].deserialize(data, config.schema);
|
|
@@ -9280,10 +9357,10 @@ function createPartitionRouter() {
|
|
|
9280
9357
|
}
|
|
9281
9358
|
|
|
9282
9359
|
// src/workers/node-worker.ts
|
|
9283
|
-
async function spawnNodeWorker(entryPoint) {
|
|
9360
|
+
async function spawnNodeWorker(entryPoint, resourceLimits) {
|
|
9284
9361
|
try {
|
|
9285
9362
|
const workerThreads = await import('worker_threads');
|
|
9286
|
-
return new workerThreads.Worker(entryPoint);
|
|
9363
|
+
return new workerThreads.Worker(entryPoint, { resourceLimits });
|
|
9287
9364
|
} catch {
|
|
9288
9365
|
return null;
|
|
9289
9366
|
}
|
|
@@ -9332,7 +9409,6 @@ function detectRuntime() {
|
|
|
9332
9409
|
}
|
|
9333
9410
|
|
|
9334
9411
|
// src/vector/hnsw-worker-dispatch.ts
|
|
9335
|
-
var BUILD_TIMEOUT_MS = 12e4;
|
|
9336
9412
|
function resolveWorkerEntryPoint() {
|
|
9337
9413
|
const base = import.meta.url;
|
|
9338
9414
|
const distIndex = base.lastIndexOf("/dist/");
|
|
@@ -9398,7 +9474,7 @@ async function dispatchWorkerBuild(docIds, vectorData, dimension, config, timeou
|
|
|
9398
9474
|
message: "No worker thread support available in the current runtime"
|
|
9399
9475
|
};
|
|
9400
9476
|
}
|
|
9401
|
-
const effectiveTimeout = timeoutMs ??
|
|
9477
|
+
const effectiveTimeout = timeoutMs ?? HNSW_BUILD_TIMEOUT_MS;
|
|
9402
9478
|
let transferBuffer;
|
|
9403
9479
|
if (skipCopy) {
|
|
9404
9480
|
transferBuffer = vectorData;
|
|
@@ -9468,7 +9544,7 @@ async function dispatchWorkerBuild(docIds, vectorData, dimension, config, timeou
|
|
|
9468
9544
|
});
|
|
9469
9545
|
}
|
|
9470
9546
|
|
|
9471
|
-
// src/vector/vector-index/
|
|
9547
|
+
// src/vector/vector-index/constants.ts
|
|
9472
9548
|
var DEFAULT_PROMOTION_THRESHOLD = 1024;
|
|
9473
9549
|
var DEFAULT_FILTER_THRESHOLD = 0.03;
|
|
9474
9550
|
var ESTIMATED_MS_PER_TOMBSTONE = 0.05;
|
|
@@ -9477,6 +9553,9 @@ var WORKER_BUILD_SIZE_THRESHOLD = 5e3;
|
|
|
9477
9553
|
var WORKER_COPY_MIN_VECTORS = 1024;
|
|
9478
9554
|
var BUILD_CHUNK_SIZE = 100;
|
|
9479
9555
|
var REBUILD_REMOVED_RATIO = 0.2;
|
|
9556
|
+
|
|
9557
|
+
// src/vector/vector-index/shared.ts
|
|
9558
|
+
var VECTOR_WORKER_COPIES_ALLOWED = { enabled: true };
|
|
9480
9559
|
function liveSize(state) {
|
|
9481
9560
|
return state.store.size - state.tombstones.size;
|
|
9482
9561
|
}
|
|
@@ -9588,6 +9667,16 @@ function recalibrateFromStore(state) {
|
|
|
9588
9667
|
sq8.recalibrateAll(storeVectors());
|
|
9589
9668
|
}
|
|
9590
9669
|
|
|
9670
|
+
// src/workers/constants.ts
|
|
9671
|
+
var WORKER_YOUNG_GENERATION_MB = 24;
|
|
9672
|
+
var MIN_WORKER_COUNT = 2;
|
|
9673
|
+
var MAX_WORKER_COUNT = 8;
|
|
9674
|
+
var FALLBACK_CPU_COUNT = 4;
|
|
9675
|
+
var DEFAULT_BACKPRESSURE_LIMIT = 100;
|
|
9676
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
9677
|
+
var SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
9678
|
+
var CONSECUTIVE_TIMEOUTS_BEFORE_DEATH = 3;
|
|
9679
|
+
|
|
9591
9680
|
// src/workers/pool.ts
|
|
9592
9681
|
function toFinite(value) {
|
|
9593
9682
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
@@ -9596,7 +9685,7 @@ function resolveWorkerCount(requested) {
|
|
|
9596
9685
|
if (requested !== void 0 && requested > 0) {
|
|
9597
9686
|
return requested;
|
|
9598
9687
|
}
|
|
9599
|
-
let cpuCount =
|
|
9688
|
+
let cpuCount = FALLBACK_CPU_COUNT;
|
|
9600
9689
|
try {
|
|
9601
9690
|
if (navigator?.hardwareConcurrency) {
|
|
9602
9691
|
cpuCount = navigator.hardwareConcurrency;
|
|
@@ -9607,9 +9696,13 @@ function resolveWorkerCount(requested) {
|
|
|
9607
9696
|
}
|
|
9608
9697
|
}
|
|
9609
9698
|
} catch {
|
|
9610
|
-
cpuCount =
|
|
9699
|
+
cpuCount = FALLBACK_CPU_COUNT;
|
|
9611
9700
|
}
|
|
9612
|
-
return Math.max(
|
|
9701
|
+
return Math.max(MIN_WORKER_COUNT, Math.min(MAX_WORKER_COUNT, cpuCount - 1));
|
|
9702
|
+
}
|
|
9703
|
+
function splitWorkerBudget(total) {
|
|
9704
|
+
const keyword = Math.ceil(total / 2);
|
|
9705
|
+
return { keyword, vector: total - keyword };
|
|
9613
9706
|
}
|
|
9614
9707
|
function createWorkerPool(config) {
|
|
9615
9708
|
const workerCount = resolveWorkerCount(config.count);
|
|
@@ -9618,29 +9711,61 @@ function createWorkerPool(config) {
|
|
|
9618
9711
|
const indexAssignment = /* @__PURE__ */ new Map();
|
|
9619
9712
|
let isShutdown = false;
|
|
9620
9713
|
function handleWorkerDeath(slotIndex, error) {
|
|
9621
|
-
if (isShutdown
|
|
9714
|
+
if (isShutdown) {
|
|
9622
9715
|
return;
|
|
9623
9716
|
}
|
|
9624
|
-
deadSlots.add(slotIndex);
|
|
9625
9717
|
const slot = workers.get(slotIndex);
|
|
9718
|
+
if (slot !== void 0 && !slot.serving) {
|
|
9719
|
+
workers.delete(slotIndex);
|
|
9720
|
+
return;
|
|
9721
|
+
}
|
|
9722
|
+
if (deadSlots.has(slotIndex)) {
|
|
9723
|
+
return;
|
|
9724
|
+
}
|
|
9725
|
+
deadSlots.add(slotIndex);
|
|
9626
9726
|
const indexNames = slot ? [...slot.indexes].sort() : [];
|
|
9627
9727
|
workers.delete(slotIndex);
|
|
9628
9728
|
config.onWorkerCrash?.(slotIndex, indexNames, error);
|
|
9629
9729
|
}
|
|
9630
|
-
function
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
indexes: /* @__PURE__ */ new Set()
|
|
9639
|
-
};
|
|
9640
|
-
workers.set(slotIndex, slot);
|
|
9641
|
-
}
|
|
9730
|
+
function spawnSlot(slotIndex, serving) {
|
|
9731
|
+
const slot = {
|
|
9732
|
+
executor: config.workerFactory(slotIndex, (error) => handleWorkerDeath(slotIndex, error)),
|
|
9733
|
+
indexes: /* @__PURE__ */ new Set(),
|
|
9734
|
+
inFlight: 0,
|
|
9735
|
+
serving
|
|
9736
|
+
};
|
|
9737
|
+
workers.set(slotIndex, slot);
|
|
9642
9738
|
return slot;
|
|
9643
9739
|
}
|
|
9740
|
+
function ensureWorker(slotIndex) {
|
|
9741
|
+
const slot = workers.get(slotIndex);
|
|
9742
|
+
if (slot !== void 0) return slot;
|
|
9743
|
+
if (deadSlots.has(slotIndex)) return void 0;
|
|
9744
|
+
return spawnSlot(slotIndex, true);
|
|
9745
|
+
}
|
|
9746
|
+
function deadWorkerIds() {
|
|
9747
|
+
return [...deadSlots].filter((slotIndex) => !workers.has(slotIndex)).sort((a, b) => a - b);
|
|
9748
|
+
}
|
|
9749
|
+
function spawnReplacement(slotIndex) {
|
|
9750
|
+
if (isShutdown || !deadSlots.has(slotIndex) || workers.has(slotIndex)) return null;
|
|
9751
|
+
const slot = spawnSlot(slotIndex, false);
|
|
9752
|
+
return {
|
|
9753
|
+
workerId: slotIndex,
|
|
9754
|
+
executor: slot.executor,
|
|
9755
|
+
hold(indexName) {
|
|
9756
|
+
slot.indexes.add(indexName);
|
|
9757
|
+
},
|
|
9758
|
+
admit() {
|
|
9759
|
+
if (workers.get(slotIndex) !== slot) return;
|
|
9760
|
+
deadSlots.delete(slotIndex);
|
|
9761
|
+
slot.serving = true;
|
|
9762
|
+
},
|
|
9763
|
+
abandon() {
|
|
9764
|
+
if (workers.get(slotIndex) === slot) workers.delete(slotIndex);
|
|
9765
|
+
void slot.executor.shutdown().catch(() => void 0);
|
|
9766
|
+
}
|
|
9767
|
+
};
|
|
9768
|
+
}
|
|
9644
9769
|
function assignSlot(indexName) {
|
|
9645
9770
|
const preferred = fnv1a(indexName) % workerCount;
|
|
9646
9771
|
for (let probe = 0; probe < workerCount; probe++) {
|
|
@@ -9679,11 +9804,11 @@ function createWorkerPool(config) {
|
|
|
9679
9804
|
throw new NarsilError(ErrorCodes.INDEX_NOT_FOUND, `Index "${indexName}" is not registered in the worker pool`);
|
|
9680
9805
|
}
|
|
9681
9806
|
const slot = workers.get(slotIndex);
|
|
9682
|
-
if (slot) {
|
|
9807
|
+
if (slot?.serving) {
|
|
9683
9808
|
return slot.executor;
|
|
9684
9809
|
}
|
|
9685
9810
|
for (const survivor of workers.values()) {
|
|
9686
|
-
if (survivor.indexes.has(indexName)) {
|
|
9811
|
+
if (survivor.serving && survivor.indexes.has(indexName)) {
|
|
9687
9812
|
return survivor.executor;
|
|
9688
9813
|
}
|
|
9689
9814
|
}
|
|
@@ -9728,6 +9853,54 @@ function createWorkerPool(config) {
|
|
|
9728
9853
|
function getAllExecutors() {
|
|
9729
9854
|
return [...workers.values()].map((slot) => slot.executor);
|
|
9730
9855
|
}
|
|
9856
|
+
function executorsHolding(indexName) {
|
|
9857
|
+
const holders = [];
|
|
9858
|
+
for (const slot of workers.values()) {
|
|
9859
|
+
if (slot.indexes.has(indexName)) holders.push(slot.executor);
|
|
9860
|
+
}
|
|
9861
|
+
return holders;
|
|
9862
|
+
}
|
|
9863
|
+
function lease(workerId, slot) {
|
|
9864
|
+
slot.inFlight += 1;
|
|
9865
|
+
let released = false;
|
|
9866
|
+
return {
|
|
9867
|
+
workerId,
|
|
9868
|
+
executor: slot.executor,
|
|
9869
|
+
release() {
|
|
9870
|
+
if (released) return;
|
|
9871
|
+
released = true;
|
|
9872
|
+
slot.inFlight -= 1;
|
|
9873
|
+
}
|
|
9874
|
+
};
|
|
9875
|
+
}
|
|
9876
|
+
function leaseLeastBusy() {
|
|
9877
|
+
let chosenId = -1;
|
|
9878
|
+
let chosen = null;
|
|
9879
|
+
for (const [workerId, slot] of workers) {
|
|
9880
|
+
if (!slot.serving) continue;
|
|
9881
|
+
if (chosen === null || slot.inFlight < chosen.inFlight) {
|
|
9882
|
+
chosenId = workerId;
|
|
9883
|
+
chosen = slot;
|
|
9884
|
+
}
|
|
9885
|
+
if (chosen.inFlight === 0) break;
|
|
9886
|
+
}
|
|
9887
|
+
return chosen === null ? null : lease(chosenId, chosen);
|
|
9888
|
+
}
|
|
9889
|
+
function queriesInFlight() {
|
|
9890
|
+
let total = 0;
|
|
9891
|
+
for (const slot of workers.values()) {
|
|
9892
|
+
if (slot.serving) total += slot.inFlight;
|
|
9893
|
+
}
|
|
9894
|
+
return total;
|
|
9895
|
+
}
|
|
9896
|
+
function leaseIdle(limit) {
|
|
9897
|
+
const leases = [];
|
|
9898
|
+
for (const [workerId, slot] of workers) {
|
|
9899
|
+
if (leases.length >= limit) break;
|
|
9900
|
+
if (slot.serving && slot.inFlight === 0) leases.push(lease(workerId, slot));
|
|
9901
|
+
}
|
|
9902
|
+
return leases;
|
|
9903
|
+
}
|
|
9731
9904
|
function addIndexToAll(indexName) {
|
|
9732
9905
|
if (isShutdown) {
|
|
9733
9906
|
throw new NarsilError(ErrorCodes.WORKER_CRASHED, "Worker pool has been shut down");
|
|
@@ -9737,9 +9910,22 @@ function createWorkerPool(config) {
|
|
|
9737
9910
|
}
|
|
9738
9911
|
indexAssignment.set(indexName, assignSlot(indexName));
|
|
9739
9912
|
}
|
|
9913
|
+
function spawnAll() {
|
|
9914
|
+
if (isShutdown) {
|
|
9915
|
+
throw new NarsilError(ErrorCodes.WORKER_CRASHED, "Worker pool has been shut down");
|
|
9916
|
+
}
|
|
9917
|
+
for (let i = 0; i < workerCount; i++) ensureWorker(i);
|
|
9918
|
+
}
|
|
9740
9919
|
return {
|
|
9741
9920
|
getExecutor,
|
|
9742
9921
|
getAllExecutors,
|
|
9922
|
+
executorsHolding,
|
|
9923
|
+
leaseLeastBusy,
|
|
9924
|
+
leaseIdle,
|
|
9925
|
+
queriesInFlight,
|
|
9926
|
+
spawnAll,
|
|
9927
|
+
deadWorkerIds,
|
|
9928
|
+
spawnReplacement,
|
|
9743
9929
|
get workerCount() {
|
|
9744
9930
|
return workerCount;
|
|
9745
9931
|
},
|
|
@@ -9751,6 +9937,9 @@ function createWorkerPool(config) {
|
|
|
9751
9937
|
};
|
|
9752
9938
|
}
|
|
9753
9939
|
|
|
9940
|
+
// src/workers/resource-limits.ts
|
|
9941
|
+
var WORKER_RESOURCE_LIMITS = { maxYoungGenerationSizeMb: WORKER_YOUNG_GENERATION_MB };
|
|
9942
|
+
|
|
9754
9943
|
// src/vector/search-pool/spawn.ts
|
|
9755
9944
|
function resolveWorkerEntryPoint2() {
|
|
9756
9945
|
const base = import.meta.url;
|
|
@@ -9764,7 +9953,7 @@ async function spawnWorker2(entryPoint) {
|
|
|
9764
9953
|
const runtime = detectRuntime();
|
|
9765
9954
|
if (runtime.supportsWorkerThreads) {
|
|
9766
9955
|
try {
|
|
9767
|
-
return await spawnNodeWorker(new URL(entryPoint));
|
|
9956
|
+
return await spawnNodeWorker(new URL(entryPoint), WORKER_RESOURCE_LIMITS);
|
|
9768
9957
|
} catch {
|
|
9769
9958
|
return null;
|
|
9770
9959
|
}
|
|
@@ -9799,8 +9988,6 @@ function listenForFailure(worker, handler) {
|
|
|
9799
9988
|
}
|
|
9800
9989
|
|
|
9801
9990
|
// src/vector/search-pool/index.ts
|
|
9802
|
-
var SEARCH_TIMEOUT_MS = 3e4;
|
|
9803
|
-
var LOAD_TIMEOUT_MS = 3e5;
|
|
9804
9991
|
async function createVectorSearchPool(requestedCount) {
|
|
9805
9992
|
const entryPoint = resolveWorkerEntryPoint2();
|
|
9806
9993
|
const count = resolveWorkerCount(requestedCount);
|
|
@@ -9863,7 +10050,7 @@ async function createVectorSearchPool(requestedCount) {
|
|
|
9863
10050
|
async function sendSearch(slot, request) {
|
|
9864
10051
|
slot.outstanding += 1;
|
|
9865
10052
|
try {
|
|
9866
|
-
return await send(slot, request.requestId, request,
|
|
10053
|
+
return await send(slot, request.requestId, request, VECTOR_SEARCH_TIMEOUT_MS);
|
|
9867
10054
|
} finally {
|
|
9868
10055
|
slot.outstanding -= 1;
|
|
9869
10056
|
}
|
|
@@ -9880,7 +10067,7 @@ async function createVectorSearchPool(requestedCount) {
|
|
|
9880
10067
|
slots.map((slot) => {
|
|
9881
10068
|
requestCounter += 1;
|
|
9882
10069
|
const requestId = `${requestCounter}`;
|
|
9883
|
-
return send(slot, requestId, { type: "load", requestId, handle, snapshot },
|
|
10070
|
+
return send(slot, requestId, { type: "load", requestId, handle, snapshot }, VECTOR_SEARCH_LOAD_TIMEOUT_MS);
|
|
9884
10071
|
})
|
|
9885
10072
|
);
|
|
9886
10073
|
return outcomes.every(
|
|
@@ -9896,7 +10083,7 @@ async function createVectorSearchPool(requestedCount) {
|
|
|
9896
10083
|
slot,
|
|
9897
10084
|
requestId,
|
|
9898
10085
|
{ type: "loadShared", requestId, handle, scratchSlot, snapshot },
|
|
9899
|
-
|
|
10086
|
+
VECTOR_SEARCH_LOAD_TIMEOUT_MS
|
|
9900
10087
|
);
|
|
9901
10088
|
})
|
|
9902
10089
|
);
|
|
@@ -9909,7 +10096,7 @@ async function createVectorSearchPool(requestedCount) {
|
|
|
9909
10096
|
slots.map((slot) => {
|
|
9910
10097
|
requestCounter += 1;
|
|
9911
10098
|
const requestId = `${requestCounter}`;
|
|
9912
|
-
return send(slot, requestId, { type: "drop", requestId, handle },
|
|
10099
|
+
return send(slot, requestId, { type: "drop", requestId, handle }, VECTOR_SEARCH_TIMEOUT_MS);
|
|
9913
10100
|
})
|
|
9914
10101
|
);
|
|
9915
10102
|
},
|
|
@@ -9977,11 +10164,11 @@ async function createVectorSearchPool(requestedCount) {
|
|
|
9977
10164
|
var sharedPool = null;
|
|
9978
10165
|
var poolHolders = 0;
|
|
9979
10166
|
var workersUnavailable = false;
|
|
9980
|
-
function acquireVectorSearchPool() {
|
|
10167
|
+
function acquireVectorSearchPool(requestedCount) {
|
|
9981
10168
|
poolHolders += 1;
|
|
9982
10169
|
if (workersUnavailable) return Promise.resolve(null);
|
|
9983
10170
|
if (sharedPool === null) {
|
|
9984
|
-
sharedPool = createVectorSearchPool().then(
|
|
10171
|
+
sharedPool = createVectorSearchPool(requestedCount).then(
|
|
9985
10172
|
(pool) => {
|
|
9986
10173
|
if (pool === null) workersUnavailable = true;
|
|
9987
10174
|
return pool;
|
|
@@ -10005,8 +10192,6 @@ async function releaseVectorSearchPool() {
|
|
|
10005
10192
|
}
|
|
10006
10193
|
|
|
10007
10194
|
// src/vector/shared-generation/layout.ts
|
|
10008
|
-
var WASM_PAGE_BYTES = 65536;
|
|
10009
|
-
var MAX_WASM_PAGES = 65536;
|
|
10010
10195
|
var SCRATCH_ALIGNMENT = 16;
|
|
10011
10196
|
function alignUp(bytes) {
|
|
10012
10197
|
return Math.ceil(bytes / SCRATCH_ALIGNMENT) * SCRATCH_ALIGNMENT;
|
|
@@ -10148,6 +10333,7 @@ function captureCloneSnapshot(state) {
|
|
|
10148
10333
|
};
|
|
10149
10334
|
}
|
|
10150
10335
|
function scheduleWorkerCopyLoad(state) {
|
|
10336
|
+
if (!state.workerCopies.enabled) return;
|
|
10151
10337
|
if (state.disposed || state.workerCopyLoading || state.building) return;
|
|
10152
10338
|
if (state.workerCopyHandle !== null) return;
|
|
10153
10339
|
if (!state.hnsw || state.buffer.size > 0) return;
|
|
@@ -10159,7 +10345,7 @@ function scheduleWorkerCopyLoad(state) {
|
|
|
10159
10345
|
}
|
|
10160
10346
|
async function loadWorkerCopies(state) {
|
|
10161
10347
|
const revision = state.revision;
|
|
10162
|
-
const pool = await acquireVectorSearchPool();
|
|
10348
|
+
const pool = await acquireVectorSearchPool(state.workerCopies.count);
|
|
10163
10349
|
if (pool === null) {
|
|
10164
10350
|
await releaseVectorSearchPool();
|
|
10165
10351
|
return;
|
|
@@ -10760,7 +10946,7 @@ function searchWithFilter(state, query, k, options, filter) {
|
|
|
10760
10946
|
}
|
|
10761
10947
|
|
|
10762
10948
|
// src/vector/vector-index/index.ts
|
|
10763
|
-
function createVectorIndex(fieldName, dimension, config) {
|
|
10949
|
+
function createVectorIndex(fieldName, dimension, config, workerCopies = VECTOR_WORKER_COPIES_ALLOWED) {
|
|
10764
10950
|
if (!Number.isInteger(dimension) || dimension <= 0) {
|
|
10765
10951
|
throw new NarsilError(
|
|
10766
10952
|
ErrorCodes.VECTOR_DIMENSION_MISMATCH,
|
|
@@ -10783,6 +10969,7 @@ function createVectorIndex(fieldName, dimension, config) {
|
|
|
10783
10969
|
filterThreshold,
|
|
10784
10970
|
quantizationMode,
|
|
10785
10971
|
hnswConfig,
|
|
10972
|
+
workerCopies,
|
|
10786
10973
|
store,
|
|
10787
10974
|
tombstones: /* @__PURE__ */ new Set(),
|
|
10788
10975
|
buffer: /* @__PURE__ */ new Set(),
|
|
@@ -10925,8 +11112,15 @@ function createVectorIndex(fieldName, dimension, config) {
|
|
|
10925
11112
|
}
|
|
10926
11113
|
|
|
10927
11114
|
// src/workers/direct-executor.ts
|
|
10928
|
-
|
|
11115
|
+
var NO_VECTOR_WORKER_COPIES = { enabled: false };
|
|
11116
|
+
function growPartitionsTo(manager, partitionId) {
|
|
11117
|
+
while (manager.partitionCount <= partitionId) {
|
|
11118
|
+
manager.addPartition();
|
|
11119
|
+
}
|
|
11120
|
+
}
|
|
11121
|
+
function createDirectExecutor(options) {
|
|
10929
11122
|
const indexes = /* @__PURE__ */ new Map();
|
|
11123
|
+
const vectorWorkerCopies = options?.vectorWorkerCopies ?? NO_VECTOR_WORKER_COPIES;
|
|
10930
11124
|
function requireIndex(indexName) {
|
|
10931
11125
|
const entry = indexes.get(indexName);
|
|
10932
11126
|
if (!entry) {
|
|
@@ -10947,7 +11141,7 @@ function createDirectExecutor() {
|
|
|
10947
11141
|
const vectorFields = extractVectorFieldsFromSchema(config.schema);
|
|
10948
11142
|
const vectorIndexes = /* @__PURE__ */ new Map();
|
|
10949
11143
|
for (const [fieldPath, dim] of vectorFields) {
|
|
10950
|
-
vectorIndexes.set(fieldPath, createVectorIndex(fieldPath, dim, config.vectorPromotion));
|
|
11144
|
+
vectorIndexes.set(fieldPath, createVectorIndex(fieldPath, dim, config.vectorPromotion, vectorWorkerCopies));
|
|
10951
11145
|
}
|
|
10952
11146
|
const manager = createPartitionManager(indexName, config, language, router, partitionCount, vectorIndexes);
|
|
10953
11147
|
indexes.set(indexName, {
|
|
@@ -11004,10 +11198,10 @@ function createDirectExecutor() {
|
|
|
11004
11198
|
case "buildSegment": {
|
|
11005
11199
|
const entry = requireIndex(action.indexName);
|
|
11006
11200
|
const segment = createPartitionIndex(0, entry.config.trackPositions ?? true);
|
|
11007
|
-
const
|
|
11201
|
+
const options2 = resolvePartitionInsertOptions(entry.config, entry.manager.analysis, action.options);
|
|
11008
11202
|
segment.beginBatch();
|
|
11009
11203
|
for (const doc of action.documents) {
|
|
11010
|
-
segment.insert(doc.docId, doc.document, entry.config.schema, entry.language,
|
|
11204
|
+
segment.insert(doc.docId, doc.document, entry.config.schema, entry.language, options2);
|
|
11011
11205
|
}
|
|
11012
11206
|
segment.endBatch();
|
|
11013
11207
|
return segment.encodeSegment();
|
|
@@ -11028,10 +11222,10 @@ function createDirectExecutor() {
|
|
|
11028
11222
|
case "attachSegments": {
|
|
11029
11223
|
const entry = requireIndex(action.indexName);
|
|
11030
11224
|
for (const segment of action.segments) {
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
entry.manager.attachFrozenSegment(segment.partitionId,
|
|
11225
|
+
growPartitionsTo(entry.manager, segment.partitionId);
|
|
11226
|
+
const frozen = createSharedFrozenSegment(segment.snapshot);
|
|
11227
|
+
for (const docId of segment.tombstonedDocIds ?? []) frozen.tombstoneDocument(docId);
|
|
11228
|
+
entry.manager.attachFrozenSegment(segment.partitionId, frozen);
|
|
11035
11229
|
}
|
|
11036
11230
|
return void 0;
|
|
11037
11231
|
}
|
|
@@ -11062,6 +11256,19 @@ function createDirectExecutor() {
|
|
|
11062
11256
|
partition.swapFrozenSegments(action.dropSegmentIds, createSharedFrozenSegment(action.snapshot));
|
|
11063
11257
|
return void 0;
|
|
11064
11258
|
}
|
|
11259
|
+
case "freezeLiveTail": {
|
|
11260
|
+
const entry = requireIndex(action.indexName);
|
|
11261
|
+
growPartitionsTo(entry.manager, action.partitionId);
|
|
11262
|
+
const tail = entry.manager.getPartition(action.partitionId);
|
|
11263
|
+
const held = isCompositePartition(tail) ? tail.live.count() : tail.count();
|
|
11264
|
+
if (held !== action.snapshot.documentCount) {
|
|
11265
|
+
console.warn(
|
|
11266
|
+
`Partition ${action.partitionId} of "${action.indexName}" held ${held} live documents where the frozen tail holds ${action.snapshot.documentCount}`
|
|
11267
|
+
);
|
|
11268
|
+
}
|
|
11269
|
+
entry.manager.replaceLiveTail(action.partitionId, createSharedFrozenSegment(action.snapshot));
|
|
11270
|
+
return void 0;
|
|
11271
|
+
}
|
|
11065
11272
|
case "remove": {
|
|
11066
11273
|
const entry = requireIndex(action.indexName);
|
|
11067
11274
|
entry.manager.remove(action.docId);
|
|
@@ -11137,7 +11344,10 @@ function createDirectExecutor() {
|
|
|
11137
11344
|
const vectorFields = extractVectorFieldsFromSchema(entry.config.schema);
|
|
11138
11345
|
const newVectorIndexes = /* @__PURE__ */ new Map();
|
|
11139
11346
|
for (const [fieldPath, dim] of vectorFields) {
|
|
11140
|
-
newVectorIndexes.set(
|
|
11347
|
+
newVectorIndexes.set(
|
|
11348
|
+
fieldPath,
|
|
11349
|
+
createVectorIndex(fieldPath, dim, entry.config.vectorPromotion, vectorWorkerCopies)
|
|
11350
|
+
);
|
|
11141
11351
|
}
|
|
11142
11352
|
entry.manager.resetVectorIndexes(newVectorIndexes);
|
|
11143
11353
|
entry.vectorIndexes = entry.manager.getVectorIndexes();
|
|
@@ -11149,9 +11359,7 @@ function createDirectExecutor() {
|
|
|
11149
11359
|
}
|
|
11150
11360
|
case "deserialize": {
|
|
11151
11361
|
const entry = requireIndex(action.indexName);
|
|
11152
|
-
|
|
11153
|
-
entry.manager.addPartition();
|
|
11154
|
-
}
|
|
11362
|
+
growPartitionsTo(entry.manager, action.partitionId);
|
|
11155
11363
|
entry.manager.deserializePartition(action.partitionId, action.data);
|
|
11156
11364
|
return void 0;
|
|
11157
11365
|
}
|
|
@@ -11183,4 +11391,4 @@ function createDirectExecutor() {
|
|
|
11183
11391
|
};
|
|
11184
11392
|
}
|
|
11185
11393
|
|
|
11186
|
-
export {
|
|
11394
|
+
export { CHECKSUM_TIMEOUT_MS, CHECKSUM_YIELD_CHUNK_BYTES, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, FIELD_FILTER_OPERATORS, FILTER_EXPRESSION_KEYS, MAX_NESTING_DEPTH, SHUTDOWN_TIMEOUT_MS, WORKER_RESOURCE_LIMITS, applyPagination, applyProjection, applySorting, buildCompactedSegmentPayload, clampRowCount, clearNormalizationCache, collectQueryTermStats, configureNormalizationCache, countsWithoutScores, createDirectExecutor, createFrozenSegment, createPartitionIndex, createPartitionManager, createPartitionRouter, createSharedFrozenSegment, createVectorIndex, createWorkerPool, decodePageCursor, deserializeMetadata, deserializePayloadV1, deserializePayloadV2, detectRuntime, encodePageCursor, encodeSegmentState, extractVectorFieldsFromSchema, fanOutMatchCount, fanOutQuery, flattenSchema, fnv1a, fnv1aBytes, freezeSegmentShared, fulltextMatches, getLanguage, getNestedValue, getNormalizationCacheSize, getStopWords, getTokenizer, hasStopWords, hasTokenizer, isCompositePartition, isNodeMainThread, isTextFieldType, kWayMerge, mergeFacets, mergePartitionStats, normalizeSort, partitionsIn, pruneStatsToQueryTerms, readSortValues, registerLanguage, registerStopWords, registerTokenizer, requireMatchingCursor, requireSortableFields, requireWithinResultWindow, resetNormalizationCache, resolveIndexAnalysis, resolveProjection, resolveWorkerCount, serializeMetadata, sortSignatureOf, spawnNodeWorker, splitWorkerBudget, tokenize, validateDocument, validateDocumentStrict, validateRequiredFields, validateSchema, validateVectorPromotion };
|