@delali/narsil 0.3.1-next.69 → 0.3.1-next.71

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.
Files changed (46) hide show
  1. package/dist/{capabilities-B1wz2Zl0.d.ts → capabilities-Dt-7B4Wz.d.ts} +2 -2
  2. package/dist/{chunk-DD5X23E6.mjs → chunk-2STVUTNA.mjs} +1 -1
  3. package/dist/chunk-3JGWULDF.mjs +256 -0
  4. package/dist/{chunk-6TGZG2TV.mjs → chunk-653BNMAF.mjs} +190 -58
  5. package/dist/{chunk-YA52AC2V.mjs → chunk-FVLQ63B7.mjs} +203 -9
  6. package/dist/{chunk-5JLSTECC.mjs → chunk-GIVAGD3Q.mjs} +1 -1
  7. package/dist/{chunk-AV4IJKD2.mjs → chunk-HWQLTLNG.mjs} +18 -1
  8. package/dist/{chunk-6IT3MH5M.mjs → chunk-IOR2K26O.mjs} +178 -238
  9. package/dist/{chunk-4VU5TWCR.mjs → chunk-LMO5TJUS.mjs} +40 -35
  10. package/dist/{chunk-BEWOA4VV.mjs → chunk-M76V3OGJ.mjs} +508 -401
  11. package/dist/{chunk-YMZCMH5M.mjs → chunk-OI42GWLR.mjs} +17 -1
  12. package/dist/{chunk-2BDG2IWP.mjs → chunk-P4DSQ6M4.mjs} +16 -6
  13. package/dist/{chunk-THYRHHO2.mjs → chunk-YJDQ7NLA.mjs} +1 -1
  14. package/dist/{client-xVrOCYTW.d.ts → client-COek5GXK.d.ts} +3 -3
  15. package/dist/client.d.ts +8 -8
  16. package/dist/{config-CEeSV_Xo.d.ts → config-Dfanyqqt.d.ts} +2 -2
  17. package/dist/{config-CSvCVtB7.d.ts → config-rBpbgTw8.d.ts} +2 -2
  18. package/dist/direct-executor-GYJEKNV5.mjs +12 -0
  19. package/dist/distribution/coordinator/etcd.d.ts +2 -2
  20. package/dist/distribution/coordinator/etcd.mjs +1 -1
  21. package/dist/distribution/coordinator/in-memory.d.ts +2 -2
  22. package/dist/distribution/coordinator/in-memory.mjs +1 -1
  23. package/dist/distribution.d.ts +8 -8
  24. package/dist/distribution.mjs +109 -69
  25. package/dist/{engine-77ErLy8P.d.ts → engine-igk0aMpQ.d.ts} +109 -60
  26. package/dist/index.browser.mjs +1167 -749
  27. package/dist/index.d.ts +7 -7
  28. package/dist/index.mjs +10 -10
  29. package/dist/invalidation/filesystem.mjs +1 -1
  30. package/dist/{memory-CKF-9WLP.d.ts → memory-C7UMCMH3.d.ts} +35 -17
  31. package/dist/persistence/durability/checkpoint-worker.d.ts +2 -1
  32. package/dist/persistence/durability/checkpoint-worker.mjs +10 -10
  33. package/dist/react.d.ts +277 -182
  34. package/dist/react.mjs +189 -45
  35. package/dist/{schema-d5Afu03A.d.ts → schema-Bgzr4g7b.d.ts} +62 -10
  36. package/dist/server.d.ts +10 -10
  37. package/dist/server.mjs +11 -7
  38. package/dist/{tasks-BEiNxDRs.d.ts → tasks-BZt_zes6.d.ts} +3 -1
  39. package/dist/{thread-FLP45EUD.mjs → thread-JEVAYETR.mjs} +6 -6
  40. package/dist/{types-DAK7mnUZ.d.ts → types-gOUqhs2F.d.ts} +1 -1
  41. package/dist/vector/search-worker.d.ts +1 -1
  42. package/dist/vector/search-worker.mjs +2 -2
  43. package/dist/workers/entry.mjs +3 -3
  44. package/package.json +7 -7
  45. package/dist/chunk-VTPLKNWI.mjs +0 -135
  46. package/dist/direct-executor-3ZYXSGFX.mjs +0 -12
@@ -1,18 +1,18 @@
1
1
  import { ReplicationMessageTypes } from './chunk-GCM3JFVA.mjs';
2
- import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, admitInsert, asBatchInsertError, embedDocumentFields, assertDocumentCarriesMappedVectors } from './chunk-YA52AC2V.mjs';
3
- import { generateId, getLanguage, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, createCompositePartition, deserializePayloadV2, createSharedFrozenSegment, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, resolveWorkerEntry, missingWorkerEntry, readHeapStatistics, resolveIndexAnalysis, deserializePayloadV1, decodeVectorIndexParts, nodeThreadId, resolveRequestThreadCount, createPartitionIndex, VECTOR_FILE_MAX_VECTORS, deadBytesFor, mergeFrozenSegments, isCompositePartition, workerResourceLimits, deserializeMetadata, isNodeMainThread, spawnNodeWorker, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, SHUTDOWN_TIMEOUT_MS, serializeMetadata, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, decodeVectorFilePayload, documentsOfPayloadV2, countDead, decodeVectorGraphPayload, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createFrozenSegment } from './chunk-BEWOA4VV.mjs';
4
- import { detectRuntime } from './chunk-AV4IJKD2.mjs';
5
- import { validateWorkerConfig, validateIndexName, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-2BDG2IWP.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-5JLSTECC.mjs';
7
- import { getNestedValue, collectQueryTermStats, mergePartitionStats, oversampledFacetConfig, fnv1a, kWayMerge, mergeFacets } from './chunk-4VU5TWCR.mjs';
8
- import { extractVectorFieldsFromSchema, validateSchema, validateVectorPromotion, validateVectorStorage, flattenSchema, isTextFieldType, validateRequiredFields, validateDocument, validateDocumentStrict } from './chunk-6TGZG2TV.mjs';
9
- import { releaseLocksHeldBy } from './chunk-THYRHHO2.mjs';
2
+ import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, restoredConfigFields, restoredEmbedding, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, admitInsert, asBatchInsertError, embedDocumentFields, assertDocumentCarriesMappedVectors, admitBufferedUpsert, createPendingAdmissions, recordPendingAdmission } from './chunk-FVLQ63B7.mjs';
3
+ import { generateId, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, createCompositePartition, deserializePayloadV2, createSharedFrozenSegment, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, resolveWorkerEntry, missingWorkerEntry, readHeapStatistics, resolveIndexAnalysis, deserializePayloadV1, decodeVectorIndexParts, nodeThreadId, resolveRequestThreadCount, createPartitionIndex, VECTOR_FILE_MAX_VECTORS, deadBytesFor, mergeFrozenSegments, isCompositePartition, workerResourceLimits, deserializeMetadata, isNodeMainThread, spawnNodeWorker, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, SHUTDOWN_TIMEOUT_MS, serializeMetadata, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, decodeVectorFilePayload, documentsOfPayloadV2, countDead, decodeVectorGraphPayload, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createFrozenSegment } from './chunk-M76V3OGJ.mjs';
4
+ import { getLanguage, detectRuntime } from './chunk-HWQLTLNG.mjs';
5
+ import { validateWorkerConfig, validateIndexName, validatePatternValueLimit, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-P4DSQ6M4.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-GIVAGD3Q.mjs';
7
+ import { getNestedValue, collectQueryTermStats, mergePartitionStats, oversampledFacetConfig, fnv1a, kWayMerge, mergeFacets } from './chunk-LMO5TJUS.mjs';
8
+ import { extractVectorFieldsFromSchema, validateSchema, validateVectorPromotion, validateVectorStorage, flattenSchema, isSingleStringFieldType, requireValidFieldTypes, validateRequiredFields, validateDocument, validateDocumentStrict } from './chunk-653BNMAF.mjs';
9
+ import { releaseLocksHeldBy } from './chunk-YJDQ7NLA.mjs';
10
10
  import { requireSearchBackendSettings } from './chunk-YNVIUGF5.mjs';
11
11
  import { crc32, nativeCrc32, crc32Final, crc32Init, crc32Update } from './chunk-3L4U6EJQ.mjs';
12
12
  import { CHECKSUM_TIMEOUT_MS, CHECKSUM_YIELD_CHUNK_BYTES } from './chunk-IFBKLBGB.mjs';
13
- import { compareCodePoints } from './chunk-YMZCMH5M.mjs';
13
+ import { compareCodePoints } from './chunk-OI42GWLR.mjs';
14
14
  import { createRequestId, isValidWorkerResponse, threadSlotOfWorker } from './chunk-POWOTUKJ.mjs';
15
- import { NarsilError, ErrorCodes } from './chunk-USKFU7J5.mjs';
15
+ import { ErrorCodes, NarsilError } from './chunk-USKFU7J5.mjs';
16
16
  import { encode, decode } from '@msgpack/msgpack';
17
17
 
18
18
  // src/engine/config-keys.ts
@@ -356,7 +356,7 @@ function validateEmbeddingConfig(embeddingConfig, schema, instanceAdapter) {
356
356
  { field: source, targetField }
357
357
  );
358
358
  }
359
- if (!isTextFieldType(sourceType)) {
359
+ if (!isSingleStringFieldType(sourceType)) {
360
360
  throw new NarsilError(
361
361
  ErrorCodes.EMBEDDING_CONFIG_INVALID,
362
362
  `Embedding source field "${source}" must be a string type, got "${sourceType}"`,
@@ -1574,6 +1574,7 @@ async function decodeSnapshotBundle(data) {
1574
1574
  if (!raw.schema || typeof raw.schema !== "object") {
1575
1575
  throw new NarsilError(ErrorCodes.PERSISTENCE_LOAD_FAILED, "Snapshot bundle missing schema");
1576
1576
  }
1577
+ requireValidFieldTypes(raw.schema);
1577
1578
  if (typeof raw.language !== "string") {
1578
1579
  throw new NarsilError(ErrorCodes.PERSISTENCE_LOAD_FAILED, "Snapshot bundle missing language");
1579
1580
  }
@@ -2533,6 +2534,7 @@ function validateManifestCommon(raw) {
2533
2534
  if (typeof raw.language !== "string") {
2534
2535
  throw new NarsilError(ErrorCodes.PERSISTENCE_LOAD_FAILED, "Segment manifest is missing language");
2535
2536
  }
2537
+ requireValidFieldTypes(raw.schema);
2536
2538
  return { schema: raw.schema, language: raw.language };
2537
2539
  }
2538
2540
  function normalizeCheckpoint2(raw) {
@@ -2953,6 +2955,9 @@ function reconstructSchemaFromMetadata(metadata) {
2953
2955
  if (metadata.vectorPromotion !== void 0) {
2954
2956
  config.vectorPromotion = metadata.vectorPromotion;
2955
2957
  }
2958
+ if (metadata.patternValueLimit !== void 0) {
2959
+ config.patternValueLimit = metadata.patternValueLimit;
2960
+ }
2956
2961
  return config;
2957
2962
  }
2958
2963
  function createEntryMessage(entry, sourceId) {
@@ -5667,6 +5672,9 @@ function buildMetadata(indexName, hooks, documentCount) {
5667
5672
  if (config.vectorPromotion !== void 0) {
5668
5673
  metadata.vectorPromotion = config.vectorPromotion;
5669
5674
  }
5675
+ if (config.patternValueLimit !== void 0) {
5676
+ metadata.patternValueLimit = config.patternValueLimit;
5677
+ }
5670
5678
  if (config.indexUuid !== void 0) {
5671
5679
  metadata.indexUuid = config.indexUuid;
5672
5680
  }
@@ -5780,7 +5788,8 @@ function createDurabilityFromTier(tier, wiring) {
5780
5788
  ...entry.config.trackPositions !== void 0 ? { trackPositions: entry.config.trackPositions } : {},
5781
5789
  ...entry.config.strict !== void 0 ? { strict: entry.config.strict } : {},
5782
5790
  ...entry.config.required !== void 0 ? { required: entry.config.required } : {},
5783
- ...entry.config.vectorPromotion !== void 0 ? { vectorPromotion: entry.config.vectorPromotion } : {}
5791
+ ...entry.config.vectorPromotion !== void 0 ? { vectorPromotion: entry.config.vectorPromotion } : {},
5792
+ ...entry.config.patternValueLimit !== void 0 ? { patternValueLimit: entry.config.patternValueLimit } : {}
5784
5793
  };
5785
5794
  },
5786
5795
  createIndexFromMetadata: wiring.createIndexFromMetadata,
@@ -5795,6 +5804,11 @@ function getVectorFieldPaths(schema) {
5795
5804
  }
5796
5805
 
5797
5806
  // src/engine/index-from-metadata.ts
5807
+ var RECOVERY_CONFIG_ERROR_CODES = /* @__PURE__ */ new Set([
5808
+ ErrorCodes.CONFIG_INVALID,
5809
+ ErrorCodes.SCHEMA_INVALID_TYPE,
5810
+ ErrorCodes.SCHEMA_INVALID_VECTOR_DIMENSION
5811
+ ]);
5798
5812
  function resolveEmbeddingAdapter(deps, metadata, schema) {
5799
5813
  const name = metadata.embedding?.adapter ?? null;
5800
5814
  if (!metadata.embedding) return { adapter: null, name };
@@ -5813,6 +5827,15 @@ function resolveEmbeddingAdapter(deps, metadata, schema) {
5813
5827
  }
5814
5828
  return { adapter: candidate, name };
5815
5829
  }
5830
+ function recoveryFailure(metadata, err) {
5831
+ if (!(err instanceof NarsilError) || !RECOVERY_CONFIG_ERROR_CODES.has(err.code)) return err;
5832
+ return new NarsilError(err.code, `Recovery of index "${metadata.indexName}" failed: ${err.message}`, {
5833
+ ...err.details,
5834
+ indexName: metadata.indexName,
5835
+ tokenizer: metadata.tokenizer,
5836
+ stopWords: metadata.stopWords
5837
+ });
5838
+ }
5816
5839
  async function createIndexFromMetadata(deps, metadata, loadData) {
5817
5840
  const existing = deps.indexRegistry.get(metadata.indexName);
5818
5841
  if (existing !== void 0) {
@@ -5823,19 +5846,18 @@ async function createIndexFromMetadata(deps, metadata, loadData) {
5823
5846
  }
5824
5847
  const indexConfig = reconstructSchemaFromMetadata(metadata);
5825
5848
  const language = getLanguage(indexConfig.language ?? "english");
5849
+ try {
5850
+ indexConfig.schema = validateSchema(indexConfig.schema);
5851
+ validatePatternValueLimit(indexConfig.patternValueLimit);
5852
+ } catch (err) {
5853
+ throw recoveryFailure(metadata, err);
5854
+ }
5826
5855
  const embedding = resolveEmbeddingAdapter(deps, metadata, indexConfig.schema);
5827
5856
  try {
5828
5857
  validateVectorStorage(indexConfig.vectorPromotion, deps.filesystemDurability);
5829
5858
  if (loadData) deps.executor.createIndex(metadata.indexName, indexConfig, language);
5830
5859
  } catch (err) {
5831
- if (err instanceof NarsilError && err.code === ErrorCodes.CONFIG_INVALID) {
5832
- throw new NarsilError(err.code, `Recovery of index "${metadata.indexName}" failed: ${err.message}`, {
5833
- indexName: metadata.indexName,
5834
- tokenizer: metadata.tokenizer,
5835
- stopWords: metadata.stopWords
5836
- });
5837
- }
5838
- throw err;
5860
+ throw recoveryFailure(metadata, err);
5839
5861
  }
5840
5862
  deps.indexRegistry.set(metadata.indexName, {
5841
5863
  config: indexConfig,
@@ -6442,21 +6464,10 @@ function createHeapPressureNotifier(deps) {
6442
6464
  }
6443
6465
 
6444
6466
  // src/engine/watermark.ts
6445
- function createWatermarkNotifier(deps) {
6467
+ function createWatermarkNotifier(deps, scope = "index") {
6446
6468
  const latchedCapacity = /* @__PURE__ */ new Map();
6447
- function check(indexName) {
6448
- const partitionConfig = deps.getPartitionConfig(indexName);
6449
- const maxDocs = partitionConfig?.maxDocsPerPartition;
6450
- const watermark = partitionConfig?.watermark;
6451
- if (maxDocs === void 0 || watermark === void 0) {
6452
- latchedCapacity.delete(indexName);
6453
- return;
6454
- }
6455
- const manager = deps.getManager(indexName);
6456
- if (!manager) {
6457
- latchedCapacity.delete(indexName);
6458
- return;
6459
- }
6469
+ const latchedPartitions = /* @__PURE__ */ new Map();
6470
+ function checkIndex(indexName, manager, maxDocs, watermark) {
6460
6471
  const partitionCount = manager.partitionCount;
6461
6472
  const capacity = maxDocs * partitionCount;
6462
6473
  const documentCount = manager.countDocuments();
@@ -6469,19 +6480,63 @@ function createWatermarkNotifier(deps) {
6469
6480
  latchedCapacity.set(indexName, capacity);
6470
6481
  deps.emit({ indexName, documentCount, capacity, partitionCount });
6471
6482
  }
6483
+ function checkPartitions(indexName, manager, maxDocs, watermark, insertedDocIds) {
6484
+ const threshold = watermark * maxDocs;
6485
+ const latched = latchedPartitions.get(indexName) ?? /* @__PURE__ */ new Set();
6486
+ latchedPartitions.set(indexName, latched);
6487
+ const checked = /* @__PURE__ */ new Set();
6488
+ for (const docId of insertedDocIds) {
6489
+ const partitionId = manager.partitionIdOf(docId) ?? manager.routePartition(docId);
6490
+ if (checked.has(partitionId)) continue;
6491
+ checked.add(partitionId);
6492
+ const documentCount = manager.getPartition(partitionId).count();
6493
+ if (documentCount < threshold) {
6494
+ latched.delete(partitionId);
6495
+ continue;
6496
+ }
6497
+ if (latched.has(partitionId)) continue;
6498
+ latched.add(partitionId);
6499
+ deps.emit({ indexName, documentCount, capacity: maxDocs, partitionCount: manager.partitionCount, partitionId });
6500
+ }
6501
+ }
6502
+ function check(indexName, inserted) {
6503
+ const partitionConfig = deps.getPartitionConfig(indexName);
6504
+ const maxDocs = partitionConfig?.maxDocsPerPartition;
6505
+ const watermark = partitionConfig?.watermark;
6506
+ if (maxDocs === void 0 || watermark === void 0) {
6507
+ forget(indexName);
6508
+ return;
6509
+ }
6510
+ const manager = deps.getManager(indexName);
6511
+ if (manager === void 0) {
6512
+ forget(indexName);
6513
+ return;
6514
+ }
6515
+ if (scope === "index") {
6516
+ checkIndex(indexName, manager, maxDocs, watermark);
6517
+ return;
6518
+ }
6519
+ if (inserted !== void 0) {
6520
+ checkPartitions(indexName, manager, maxDocs, watermark, typeof inserted === "string" ? [inserted] : inserted);
6521
+ }
6522
+ }
6472
6523
  function forget(indexName) {
6473
6524
  latchedCapacity.delete(indexName);
6525
+ latchedPartitions.delete(indexName);
6474
6526
  }
6475
6527
  return { check, forget };
6476
6528
  }
6477
6529
 
6478
6530
  // src/engine/notifiers.ts
6479
6531
  function wireWatermarkNotifier(wiring) {
6480
- return createWatermarkNotifier({
6481
- getManager: wiring.getManager,
6482
- getPartitionConfig: (indexName) => wiring.indexRegistry.get(indexName)?.config.partitions,
6483
- emit: (payload) => emitEngineEvent(wiring.eventHandlers, "partitionWatermark", payload)
6484
- });
6532
+ return createWatermarkNotifier(
6533
+ {
6534
+ getManager: wiring.getManager,
6535
+ getPartitionConfig: (indexName) => wiring.indexRegistry.get(indexName)?.config.partitions,
6536
+ emit: (payload) => emitEngineEvent(wiring.eventHandlers, "partitionWatermark", payload)
6537
+ },
6538
+ wiring.capacityScope
6539
+ );
6485
6540
  }
6486
6541
  function warnUnheardHeapPressure(payload) {
6487
6542
  console.warn(
@@ -8452,8 +8507,32 @@ function createWorkerOrchestrator(config, executor, indexRegistry, callbacks, ve
8452
8507
  };
8453
8508
  }
8454
8509
 
8510
+ // src/engine/mutations/write-visibility.ts
8511
+ async function awaitWriteVisibility(ctx, indexName) {
8512
+ await ctx.awaitRebalanceReplay(indexName);
8513
+ await ctx.orchestrator.awaitWrites(indexName);
8514
+ }
8515
+
8516
+ // src/engine/write-events.ts
8517
+ var WRITE_EVENT = "write";
8518
+ function emitWriteEvent(source, indexName) {
8519
+ const handlers = source.eventHandlers.get(WRITE_EVENT);
8520
+ if (handlers === void 0 || handlers.size === 0) return;
8521
+ const emit = () => {
8522
+ emitEngineEvent(source.eventHandlers, WRITE_EVENT, { indexName });
8523
+ };
8524
+ awaitWriteVisibility(source.mutationCtx, indexName).then(emit, emit);
8525
+ }
8526
+ async function emitWriteEventAfter(source, indexName, write) {
8527
+ try {
8528
+ return await write;
8529
+ } finally {
8530
+ emitWriteEvent(source, indexName);
8531
+ }
8532
+ }
8533
+
8455
8534
  // src/engine/core.ts
8456
- function createEngineCore(config, hooks) {
8535
+ function createEngineCore(config, hooks, capacityScope = "index") {
8457
8536
  validateWorkerConfig(config?.workers, config?.lifecycle);
8458
8537
  const vectorWorkerCount = splitWorkerBudget(resolveWorkerCount(config?.workers?.count)).vector;
8459
8538
  const vectorCopyPolicy = {
@@ -8591,7 +8670,11 @@ function createEngineCore(config, hooks) {
8591
8670
  }
8592
8671
  return names;
8593
8672
  },
8594
- reloadIndex: (indexName) => durability?.manager.reloadIndex?.(indexName) ?? Promise.resolve(),
8673
+ reloadIndex: (indexName) => emitWriteEventAfter(
8674
+ { eventHandlers, mutationCtx },
8675
+ indexName,
8676
+ durability?.manager.reloadIndex?.(indexName) ?? Promise.resolve()
8677
+ ),
8595
8678
  onError(error) {
8596
8679
  if (emitEngineEvent(eventHandlers, "invalidationError", { error }) === 0) {
8597
8680
  console.warn("Invalidation error:", error);
@@ -8601,7 +8684,8 @@ function createEngineCore(config, hooks) {
8601
8684
  const notifierWiring = {
8602
8685
  eventHandlers,
8603
8686
  indexRegistry,
8604
- getManager: (indexName) => executor.getManager(indexName)
8687
+ getManager: (indexName) => executor.getManager(indexName),
8688
+ capacityScope
8605
8689
  };
8606
8690
  const watermarkNotifier = wireWatermarkNotifier(notifierWiring);
8607
8691
  const heapPressureNotifier = wireHeapPressureNotifier(notifierWiring);
@@ -8645,6 +8729,7 @@ function createEngineCore(config, hooks) {
8645
8729
  pendingRebalanceWrites: (indexName) => waqMap.get(indexName)?.size ?? 0,
8646
8730
  rebalanceTargetPartitionCount: (indexName) => rebalanceTargets.get(indexName),
8647
8731
  bufferedDocState: (indexName, docId) => waqMap.get(indexName)?.bufferedDocState(docId),
8732
+ capacityScope,
8648
8733
  checkWatermark: watermarkNotifier.check,
8649
8734
  checkHeapPressure: heapPressureNotifier.check
8650
8735
  };
@@ -8778,13 +8863,16 @@ async function runLifecycleHook(core, hookName, context) {
8778
8863
  async function announceIndexCreated(core, name, config) {
8779
8864
  await runLifecycleHook(core, "onIndexCreate", { indexName: name, config });
8780
8865
  }
8781
- async function createEngineIndex(core, config, name, indexConfig, indexUuid) {
8866
+ async function createEngineIndex(core, config, name, requestedConfig, creation = {}) {
8867
+ const { indexUuid, adapterBinding = "required" } = creation;
8782
8868
  core.guardShutdown();
8783
8869
  validateIndexName(name);
8784
8870
  if (core.indexRegistry.has(name)) {
8785
8871
  throw new NarsilError(ErrorCodes.INDEX_ALREADY_EXISTS, `Index "${name}" already exists`, { indexName: name });
8786
8872
  }
8787
- validateSchema(indexConfig.schema);
8873
+ const schema = validateSchema(requestedConfig.schema);
8874
+ const indexConfig = schema === requestedConfig.schema ? requestedConfig : { ...requestedConfig, schema };
8875
+ validatePatternValueLimit(indexConfig.patternValueLimit);
8788
8876
  validateVectorPromotion(indexConfig.vectorPromotion);
8789
8877
  validateVectorStorage(indexConfig.vectorPromotion, core.filesystemDurability);
8790
8878
  validateBM25Params(indexConfig.bm25);
@@ -8810,24 +8898,31 @@ async function createEngineIndex(core, config, name, indexConfig, indexUuid) {
8810
8898
  let resolvedEmbeddingAdapter = null;
8811
8899
  let embeddingAdapterName = null;
8812
8900
  if (indexConfig.embedding) {
8813
- let configuredAdapter = indexConfig.embedding.adapter;
8901
+ const configuredAdapter = indexConfig.embedding.adapter;
8902
+ const fields = indexConfig.embedding.fields;
8814
8903
  if (typeof configuredAdapter === "string") {
8815
8904
  embeddingAdapterName = configuredAdapter;
8816
8905
  const registered = core.embeddingAdapters.get(configuredAdapter);
8817
- if (!registered) {
8906
+ if (registered !== void 0) {
8907
+ resolvedEmbeddingAdapter = validateEmbeddingConfig(
8908
+ { fields, adapter: registered },
8909
+ indexConfig.schema,
8910
+ config?.embedding
8911
+ );
8912
+ } else if (adapterBinding === "required") {
8818
8913
  throw new NarsilError(
8819
8914
  ErrorCodes.EMBEDDING_CONFIG_INVALID,
8820
8915
  `Embedding adapter "${configuredAdapter}" is not registered on this engine`,
8821
8916
  { adapter: configuredAdapter, available: [...core.embeddingAdapters.keys()] }
8822
8917
  );
8823
8918
  }
8824
- configuredAdapter = registered;
8919
+ } else if (adapterBinding === "required" || configuredAdapter !== void 0 || config?.embedding !== void 0) {
8920
+ resolvedEmbeddingAdapter = validateEmbeddingConfig(
8921
+ { fields, adapter: configuredAdapter },
8922
+ indexConfig.schema,
8923
+ config?.embedding
8924
+ );
8825
8925
  }
8826
- resolvedEmbeddingAdapter = validateEmbeddingConfig(
8827
- { fields: indexConfig.embedding.fields, adapter: configuredAdapter },
8828
- indexConfig.schema,
8829
- config?.embedding
8830
- );
8831
8926
  }
8832
8927
  if (indexConfig.required && indexConfig.required.length > 0) {
8833
8928
  validateRequiredFieldsInSchema(indexConfig.required, indexConfig.schema);
@@ -8944,12 +9039,6 @@ async function rollbackUpdatedDocument(ctx, indexName, docId, restoreDoc, origin
8944
9039
  }
8945
9040
  }
8946
9041
 
8947
- // src/engine/mutations/write-visibility.ts
8948
- async function awaitWriteVisibility(ctx, indexName) {
8949
- await ctx.awaitRebalanceReplay(indexName);
8950
- await ctx.orchestrator.awaitWrites(indexName);
8951
- }
8952
-
8953
9042
  // src/engine/mutations/insert.ts
8954
9043
  async function insertDocument(ctx, indexName, document, docId, options) {
8955
9044
  ctx.guardShutdown();
@@ -9042,7 +9131,7 @@ async function insertDocument(ctx, indexName, document, docId, options) {
9042
9131
  await applyInsert();
9043
9132
  }
9044
9133
  if (buffered) {
9045
- ctx.checkWatermark(indexName);
9134
+ ctx.checkWatermark(indexName, resolvedDocId);
9046
9135
  ctx.checkHeapPressure(indexName);
9047
9136
  if (options?.wait === true) await awaitWriteVisibility(ctx, indexName);
9048
9137
  return resolvedDocId;
@@ -9066,7 +9155,7 @@ async function insertDocument(ctx, indexName, document, docId, options) {
9066
9155
  vecIndex.scheduleBuild();
9067
9156
  }
9068
9157
  }
9069
- ctx.checkWatermark(indexName);
9158
+ ctx.checkWatermark(indexName, resolvedDocId);
9070
9159
  ctx.checkHeapPressure(indexName);
9071
9160
  await ctx.orchestrator.scaleOutReadyIndexes();
9072
9161
  if (options?.wait === true) await awaitWriteVisibility(ctx, indexName);
@@ -9177,6 +9266,7 @@ async function admitBatchDocuments(ctx, indexName, documents, failed) {
9177
9266
  const required = entry.config.required;
9178
9267
  const admitted = [];
9179
9268
  const admittedIds = /* @__PURE__ */ new Set();
9269
+ const pending = createPendingAdmissions();
9180
9270
  for (let chunkStart = 0; chunkStart < documents.length; chunkStart += BATCH_CHUNK_SIZE) {
9181
9271
  if (ctx.abortController.signal.aborted) break;
9182
9272
  const chunkEnd = Math.min(chunkStart + BATCH_CHUNK_SIZE, documents.length);
@@ -9209,15 +9299,16 @@ async function admitBatchDocuments(ctx, indexName, documents, failed) {
9209
9299
  if (extractedVectors.size > 0) {
9210
9300
  validateVectorDimensions(extractedVectors, vecIndexes);
9211
9301
  }
9212
- admitInsert(ctx, indexName, manager, docId, admitted.length);
9302
+ admitInsert(ctx, indexName, manager, docId, pending);
9213
9303
  if (admittedIds.has(docId) || manager.has(docId)) {
9214
9304
  throw new NarsilError(ErrorCodes.DOC_ALREADY_EXISTS, `Document "${docId}" already exists`, { docId });
9215
9305
  }
9216
- validateDocument(partitionDoc, entry.config.schema);
9306
+ validateDocument(partitionDoc, entry.config.schema, entry.config.patternValueLimit);
9217
9307
  if (strict) {
9218
9308
  validateDocumentStrict(partitionDoc, entry.config.schema);
9219
9309
  }
9220
9310
  admittedIds.add(docId);
9311
+ recordPendingAdmission(ctx, pending, manager, docId);
9221
9312
  admitted.push({ docId, document: documents[i], partitionDoc, extractedVectors });
9222
9313
  } catch (err) {
9223
9314
  failed.push({ docId, error: asBatchInsertError(err) });
@@ -9616,7 +9707,7 @@ async function insertBatchViaSegments(ctx, indexName, documents, options) {
9616
9707
  for (const fieldPath of outcome.touchedVectorFields) {
9617
9708
  vecIndexes.get(fieldPath)?.scheduleBuild();
9618
9709
  }
9619
- ctx.checkWatermark(indexName);
9710
+ ctx.checkWatermark(indexName, outcome.succeeded);
9620
9711
  ctx.checkHeapPressure(indexName);
9621
9712
  await ctx.orchestrator.scaleOutReadyIndexes();
9622
9713
  if (options?.wait === true) await awaitWriteVisibility(ctx, indexName);
@@ -9749,7 +9840,7 @@ async function insertDocumentBatch(ctx, indexName, documents, options) {
9749
9840
  vecIndex.scheduleBuild();
9750
9841
  }
9751
9842
  }
9752
- ctx.checkWatermark(indexName);
9843
+ ctx.checkWatermark(indexName, succeeded);
9753
9844
  ctx.checkHeapPressure(indexName);
9754
9845
  await ctx.orchestrator.scaleOutReadyIndexes();
9755
9846
  if (options?.wait === true) await awaitWriteVisibility(ctx, indexName);
@@ -9982,7 +10073,7 @@ function applyOfUpdate(ctx, indexName, prepared) {
9982
10073
  const bufferedState = ctx.bufferedDocState(indexName, docId);
9983
10074
  const exists = bufferedState !== void 0 ? bufferedState === "present" : manager.has(docId);
9984
10075
  if (!exists) {
9985
- manager.assertCapacity(ctx.pendingRebalanceWrites(indexName), ctx.rebalanceTargetPartitionCount(indexName));
10076
+ admitBufferedUpsert(ctx, indexName, manager, docId);
9986
10077
  }
9987
10078
  }
9988
10079
  if (ctx.bufferIfRebalancing(indexName, { action: "update", docId, document, indexName })) {
@@ -10341,162 +10432,6 @@ async function executeRebalance(manager, indexName, targetPartitionCount, ctx) {
10341
10432
  ctx.checkWatermark(indexName);
10342
10433
  }
10343
10434
 
10344
- // src/engine/snapshot/restore-config.ts
10345
- function invalid2(message) {
10346
- throw new NarsilError(ErrorCodes.DOC_VALIDATION_FAILED, `Invalid snapshot: ${message}`);
10347
- }
10348
- function isPlainObject(value) {
10349
- return value !== null && typeof value === "object" && !Array.isArray(value);
10350
- }
10351
- function restoredBm25(raw) {
10352
- if (raw === void 0) {
10353
- return void 0;
10354
- }
10355
- if (!isPlainObject(raw)) {
10356
- invalid2("bm25 must be an object");
10357
- }
10358
- const { k1, b } = raw;
10359
- if (k1 !== void 0 && (typeof k1 !== "number" || !Number.isFinite(k1))) {
10360
- invalid2("bm25 k1 must be a finite number");
10361
- }
10362
- if (b !== void 0 && (typeof b !== "number" || !Number.isFinite(b))) {
10363
- invalid2("bm25 b must be a finite number");
10364
- }
10365
- return {
10366
- ...k1 !== void 0 ? { k1 } : {},
10367
- ...b !== void 0 ? { b } : {}
10368
- };
10369
- }
10370
- function restoredStopWords(name, list) {
10371
- if (name !== void 0 && typeof name !== "string") {
10372
- invalid2("stopWords must be a name");
10373
- }
10374
- if (list !== void 0 && (!Array.isArray(list) || !list.every((word) => typeof word === "string"))) {
10375
- invalid2("stopWordList must be a list of words");
10376
- }
10377
- if (typeof name === "string" && Array.isArray(list)) {
10378
- invalid2("stopWords and stopWordList cannot both be present");
10379
- }
10380
- if (typeof name === "string") {
10381
- return name;
10382
- }
10383
- if (Array.isArray(list)) {
10384
- return new Set(list);
10385
- }
10386
- return void 0;
10387
- }
10388
- function restoredPartitionConfig(raw) {
10389
- if (raw === void 0) {
10390
- return void 0;
10391
- }
10392
- if (!isPlainObject(raw)) {
10393
- invalid2("partitionConfig must be an object");
10394
- }
10395
- const { maxDocsPerPartition, maxPartitions, watermark } = raw;
10396
- if (maxDocsPerPartition !== void 0 && (typeof maxDocsPerPartition !== "number" || !Number.isInteger(maxDocsPerPartition) || maxDocsPerPartition < 1)) {
10397
- invalid2("partitionConfig maxDocsPerPartition must be a positive integer");
10398
- }
10399
- if (maxPartitions !== void 0 && (typeof maxPartitions !== "number" || !Number.isInteger(maxPartitions) || maxPartitions < 1)) {
10400
- invalid2("partitionConfig maxPartitions must be a positive integer");
10401
- }
10402
- if (watermark !== void 0 && (typeof watermark !== "number" || !(watermark > 0) || watermark > 1)) {
10403
- invalid2("partitionConfig watermark must be above 0 and at most 1");
10404
- }
10405
- return {
10406
- ...typeof maxDocsPerPartition === "number" ? { maxDocsPerPartition } : {},
10407
- ...typeof maxPartitions === "number" ? { maxPartitions } : {},
10408
- ...typeof watermark === "number" ? { watermark } : {}
10409
- };
10410
- }
10411
- function restoredScoring(raw) {
10412
- if (raw === void 0) {
10413
- return void 0;
10414
- }
10415
- if (raw !== "local" && raw !== "dfs" && raw !== "broadcast") {
10416
- invalid2("defaultScoring must be 'local', 'dfs', or 'broadcast'");
10417
- }
10418
- return raw;
10419
- }
10420
- function restoredBoolean(raw, field) {
10421
- if (raw === void 0) {
10422
- return void 0;
10423
- }
10424
- if (typeof raw !== "boolean") {
10425
- invalid2(`${field} must be a boolean`);
10426
- }
10427
- return raw;
10428
- }
10429
- function restoredRequired(raw) {
10430
- if (raw === void 0) {
10431
- return void 0;
10432
- }
10433
- if (!Array.isArray(raw) || !raw.every((field) => typeof field === "string")) {
10434
- invalid2("required must be a list of field paths");
10435
- }
10436
- return raw;
10437
- }
10438
- function restoredVectorPromotion(raw) {
10439
- if (raw === void 0) {
10440
- return void 0;
10441
- }
10442
- if (!isPlainObject(raw) || raw.hnswConfig !== void 0 && !isPlainObject(raw.hnswConfig)) {
10443
- invalid2("vectorPromotion must be an object");
10444
- }
10445
- return raw;
10446
- }
10447
- function restoredEmbedding(raw) {
10448
- if (raw === void 0) {
10449
- return void 0;
10450
- }
10451
- if (!isPlainObject(raw)) {
10452
- invalid2("embedding must be an object");
10453
- }
10454
- const { fields, adapter } = raw;
10455
- if (adapter !== void 0 && typeof adapter !== "string") {
10456
- invalid2("embedding adapter must be a name");
10457
- }
10458
- if (!isPlainObject(fields)) {
10459
- invalid2("embedding fields must be an object");
10460
- }
10461
- for (const value of Object.values(fields)) {
10462
- const isPath = typeof value === "string";
10463
- const isPathList = Array.isArray(value) && value.every((path) => typeof path === "string");
10464
- if (!isPath && !isPathList) {
10465
- invalid2("embedding fields must map vector fields to source paths");
10466
- }
10467
- }
10468
- return {
10469
- fields,
10470
- ...adapter !== void 0 ? { adapter } : {}
10471
- };
10472
- }
10473
- function restoredConfigFields(envelope) {
10474
- if (envelope.tokenizer !== void 0 && typeof envelope.tokenizer !== "string") {
10475
- invalid2("tokenizer must be a name");
10476
- }
10477
- const stopWords = restoredStopWords(envelope.stopWords, envelope.stopWordList);
10478
- const bm25 = restoredBm25(envelope.bm25);
10479
- const surfaceForms = restoredBoolean(envelope.surfaceForms, "surfaceForms");
10480
- const partitions = restoredPartitionConfig(envelope.partitionConfig);
10481
- const defaultScoring = restoredScoring(envelope.defaultScoring);
10482
- const trackPositions = restoredBoolean(envelope.trackPositions, "trackPositions");
10483
- const strict = restoredBoolean(envelope.strict, "strict");
10484
- const required = restoredRequired(envelope.required);
10485
- const vectorPromotion = restoredVectorPromotion(envelope.vectorPromotion);
10486
- return {
10487
- ...typeof envelope.tokenizer === "string" ? { tokenizer: envelope.tokenizer } : {},
10488
- ...stopWords !== void 0 ? { stopWords } : {},
10489
- ...bm25 !== void 0 ? { bm25 } : {},
10490
- ...surfaceForms !== void 0 ? { surfaceForms } : {},
10491
- ...partitions !== void 0 ? { partitions } : {},
10492
- ...defaultScoring !== void 0 ? { defaultScoring } : {},
10493
- ...trackPositions !== void 0 ? { trackPositions } : {},
10494
- ...strict !== void 0 ? { strict } : {},
10495
- ...required !== void 0 ? { required } : {},
10496
- ...vectorPromotion !== void 0 ? { vectorPromotion } : {}
10497
- };
10498
- }
10499
-
10500
10435
  // src/engine/snapshot/index.ts
10501
10436
  async function recordRestoredDocuments(durability, indexName, restored) {
10502
10437
  if (restored.length === 0) return;
@@ -10552,6 +10487,7 @@ async function createSnapshot(manager, entry) {
10552
10487
  ...config.strict !== void 0 ? { strict: config.strict } : {},
10553
10488
  ...config.required !== void 0 ? { required: config.required } : {},
10554
10489
  ...config.vectorPromotion !== void 0 ? { vectorPromotion: config.vectorPromotion } : {},
10490
+ ...config.patternValueLimit !== void 0 ? { patternValueLimit: config.patternValueLimit } : {},
10555
10491
  ...config.embedding !== void 0 ? {
10556
10492
  embedding: {
10557
10493
  fields: config.embedding.fields,
@@ -10604,8 +10540,8 @@ async function restoreFromSnapshot(indexName, data, deps) {
10604
10540
  const configFields = restoredConfigFields(envelope);
10605
10541
  const embedding = restoredEmbedding(envelope.embedding);
10606
10542
  const language = getLanguage(envelope.language);
10607
- const schema = envelope.schema;
10608
- validateSchema(schema);
10543
+ const schema = validateSchema(envelope.schema);
10544
+ validatePatternValueLimit(configFields.patternValueLimit);
10609
10545
  validateVectorPromotion(configFields.vectorPromotion);
10610
10546
  validateVectorStorage(configFields.vectorPromotion, deps.filesystemDurability);
10611
10547
  if (configFields.required !== void 0 && configFields.required.length > 0) {
@@ -10971,15 +10907,18 @@ function createNarsilFromCore(core, config) {
10971
10907
  release();
10972
10908
  }
10973
10909
  }
10910
+ function withOpenIndexWrite(indexName, action) {
10911
+ return emitWriteEventAfter(core, indexName, withOpenIndex(indexName, action));
10912
+ }
10974
10913
  const narsil = {
10975
10914
  createIndex(name, indexConfig) {
10976
- return createEngineIndex(core, config, name, indexConfig);
10915
+ return emitWriteEventAfter(core, name, createEngineIndex(core, config, name, indexConfig));
10977
10916
  },
10978
10917
  registerEmbeddingAdapter(name, adapter) {
10979
10918
  registerEngineEmbeddingAdapter(core, name, adapter);
10980
10919
  },
10981
10920
  dropIndex(name) {
10982
- return dropEngineIndex(core, name);
10921
+ return emitWriteEventAfter(core, name, dropEngineIndex(core, name));
10983
10922
  },
10984
10923
  open(indexName) {
10985
10924
  guardShutdown();
@@ -11025,22 +10964,22 @@ function createNarsilFromCore(core, config) {
11025
10964
  return executor.getManager(indexName)?.getPartitionStats() ?? [];
11026
10965
  },
11027
10966
  insert(indexName, document, docId, options) {
11028
- return withOpenIndex(indexName, () => insertDocument(mutationCtx, indexName, document, docId, options));
10967
+ return withOpenIndexWrite(indexName, () => insertDocument(mutationCtx, indexName, document, docId, options));
11029
10968
  },
11030
10969
  insertBatch(indexName, documents, options) {
11031
- return withOpenIndex(indexName, () => insertDocumentBatch(mutationCtx, indexName, documents, options));
10970
+ return withOpenIndexWrite(indexName, () => insertDocumentBatch(mutationCtx, indexName, documents, options));
11032
10971
  },
11033
10972
  remove(indexName, docId, options) {
11034
- return withOpenIndex(indexName, () => removeDocument(mutationCtx, indexName, docId, options));
10973
+ return withOpenIndexWrite(indexName, () => removeDocument(mutationCtx, indexName, docId, options));
11035
10974
  },
11036
10975
  removeBatch(indexName, docIds, options) {
11037
- return withOpenIndex(indexName, () => removeDocumentBatch(mutationCtx, indexName, docIds, options));
10976
+ return withOpenIndexWrite(indexName, () => removeDocumentBatch(mutationCtx, indexName, docIds, options));
11038
10977
  },
11039
10978
  update(indexName, docId, document, options) {
11040
- return withOpenIndex(indexName, () => updateDocument(mutationCtx, indexName, docId, document, options));
10979
+ return withOpenIndexWrite(indexName, () => updateDocument(mutationCtx, indexName, docId, document, options));
11041
10980
  },
11042
10981
  updateBatch(indexName, updates, options) {
11043
- return withOpenIndex(indexName, () => updateDocumentBatch(mutationCtx, indexName, updates, options));
10982
+ return withOpenIndexWrite(indexName, () => updateDocumentBatch(mutationCtx, indexName, updates, options));
11044
10983
  },
11045
10984
  waitForWrites(indexName) {
11046
10985
  guardShutdown();
@@ -11088,7 +11027,7 @@ function createNarsilFromCore(core, config) {
11088
11027
  async rebuildAnalysis(indexName) {
11089
11028
  guardShutdown();
11090
11029
  requireIndex(indexName);
11091
- await withOpenIndex(indexName, () => core.analysisRebuild.rebuild(indexName));
11030
+ await withOpenIndexWrite(indexName, () => core.analysisRebuild.rebuild(indexName));
11092
11031
  },
11093
11032
  async snapshot(indexName) {
11094
11033
  guardShutdown();
@@ -11096,11 +11035,11 @@ function createNarsilFromCore(core, config) {
11096
11035
  },
11097
11036
  async restore(indexName, data) {
11098
11037
  guardShutdown();
11099
- await restoreFromSnapshot(indexName, data, {
11038
+ const restored = restoreFromSnapshot(indexName, data, {
11100
11039
  executor,
11101
11040
  indexRegistry,
11102
11041
  getVectorFieldPaths,
11103
- dropIndex: narsil.dropIndex.bind(narsil),
11042
+ dropIndex: (name) => dropEngineIndex(core, name),
11104
11043
  announceIndexCreated: (name, restoredConfig) => announceIndexCreated(core, name, restoredConfig),
11105
11044
  requireManager,
11106
11045
  durability,
@@ -11111,6 +11050,7 @@ function createNarsilFromCore(core, config) {
11111
11050
  clearAnalysisStale: core.analysisRebuild.clearStale,
11112
11051
  indexState: core.indexState
11113
11052
  });
11053
+ await emitWriteEventAfter(core, indexName, restored);
11114
11054
  core.heapPressureNotifier.check(indexName);
11115
11055
  },
11116
11056
  async checkpoint(indexName) {
@@ -11123,7 +11063,7 @@ function createNarsilFromCore(core, config) {
11123
11063
  async clear(indexName) {
11124
11064
  guardShutdown();
11125
11065
  requireIndex(indexName);
11126
- await withOpenIndex(indexName, async () => {
11066
+ await withOpenIndexWrite(indexName, async () => {
11127
11067
  await executor.execute({ type: "clear", indexName, requestId: indexName });
11128
11068
  await orchestrator.replicateToWorkers({ type: "clear", indexName, requestId: `replicate-clear-${indexName}` });
11129
11069
  core.watermarkNotifier.forget(indexName);
@@ -11132,7 +11072,7 @@ function createNarsilFromCore(core, config) {
11132
11072
  async rebalance(indexName, targetPartitionCount) {
11133
11073
  guardShutdown();
11134
11074
  requireIndex(indexName);
11135
- return withOpenIndex(
11075
+ return withOpenIndexWrite(
11136
11076
  indexName,
11137
11077
  () => executeRebalance(requireManager(indexName), indexName, targetPartitionCount, rebalanceCtx)
11138
11078
  );
@@ -11198,14 +11138,14 @@ function createNarsilFromCore(core, config) {
11198
11138
  async compactVectors(indexName, fieldName) {
11199
11139
  guardShutdown();
11200
11140
  requireIndex(indexName);
11201
- await withOpenIndex(indexName, async () => {
11141
+ await withOpenIndexWrite(indexName, async () => {
11202
11142
  compactVectors(requireManager(indexName), indexName, fieldName);
11203
11143
  });
11204
11144
  },
11205
11145
  async optimizeVectors(indexName, fieldName) {
11206
11146
  guardShutdown();
11207
11147
  requireIndex(indexName);
11208
- await withOpenIndex(indexName, () => optimizeVectors(requireManager(indexName), indexName, fieldName));
11148
+ await withOpenIndexWrite(indexName, () => optimizeVectors(requireManager(indexName), indexName, fieldName));
11209
11149
  },
11210
11150
  vectorMaintenanceStatus(indexName) {
11211
11151
  guardShutdown();