@delali/narsil 0.2.2 → 0.2.3-next.32
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 +12 -9
- package/dist/adapters/filesystem.d.ts +1 -1
- package/dist/adapters/filesystem.mjs +1 -1
- package/dist/adapters/indexeddb.d.ts +1 -1
- package/dist/adapters/indexeddb.mjs +1 -1
- package/dist/adapters/memory.d.ts +1 -1
- package/dist/{adapters-CVqI5NBt.d.ts → adapters-79OIa4xm.d.ts} +1 -1
- package/dist/brute-force-DbHYCTc3.d.ts +8 -0
- package/dist/chunk-BFIH7OV5.mjs +185 -0
- package/dist/chunk-C6VVLMRX.mjs +63 -0
- package/dist/{chunk-UNJZ7ZDB.mjs → chunk-EMI63EXP.mjs} +33 -2
- package/dist/chunk-MFFAJ2NR.mjs +135 -0
- package/dist/chunk-OBXS7OZM.mjs +376 -0
- package/dist/{chunk-ASI6AOW2.mjs → chunk-RO4EFWE6.mjs} +7833 -3524
- package/dist/{chunk-WLR5BFL3.mjs → chunk-TEAJO7CU.mjs} +3067 -2087
- package/dist/{chunk-S7RJJMHI.mjs → chunk-WDL632CN.mjs} +699 -222
- package/dist/{chunk-BKAI2WXI.mjs → chunk-WTONLDU3.mjs} +5 -0
- package/dist/client-DQHB_swQ.d.ts +793 -0
- package/dist/client.d.ts +6 -0
- package/dist/client.mjs +843 -0
- package/dist/{config-DXypXAfN.d.ts → config-ChZ7lfqc.d.ts} +3 -3
- package/dist/direct-executor-YARCDMJF.mjs +8 -0
- package/dist/distribution/coordinator/etcd.d.ts +3 -3
- package/dist/distribution/coordinator/etcd.mjs +471 -2
- package/dist/distribution/coordinator/in-memory.d.ts +3 -3
- package/dist/distribution/coordinator/in-memory.mjs +286 -1
- package/dist/distribution/transport/grpc.d.ts +45 -0
- package/dist/distribution/transport/grpc.mjs +586 -0
- package/dist/distribution/transport/in-memory.d.ts +118 -0
- package/dist/distribution/transport/in-memory.mjs +214 -0
- package/dist/distribution/transport/tcp.d.ts +27 -0
- package/dist/distribution/transport/tcp.mjs +595 -0
- package/dist/distribution.d.ts +241 -192
- package/dist/distribution.mjs +6620 -4795
- package/dist/embeddings/openai.d.ts +1 -1
- package/dist/embeddings/openai.mjs +1 -1
- package/dist/{engine-CO9Wnfie.d.ts → engine-DScGlT2Z.d.ts} +30 -3
- package/dist/index.browser.mjs +10035 -3914
- package/dist/index.d.ts +8 -8
- package/dist/index.mjs +8 -5
- package/dist/invalidation/broadcast-channel.d.ts +1 -1
- package/dist/invalidation/filesystem.d.ts +1 -1
- package/dist/invalidation/filesystem.mjs +3 -1
- package/dist/invalidation/noop.d.ts +1 -1
- package/dist/options-BORJg5XB.d.ts +234 -0
- package/dist/persistence/durability/checkpoint-worker.d.ts +4 -2
- package/dist/persistence/durability/checkpoint-worker.mjs +8 -5
- package/dist/react.d.ts +340 -0
- package/dist/react.mjs +687 -0
- package/dist/{schema-CE6S_aAr.d.ts → schema-emTQfEiX.d.ts} +21 -7
- package/dist/{search-DLBtiPdQ.d.ts → search-CQ-9bKxo.d.ts} +226 -14
- package/dist/server.d.ts +42 -356
- package/dist/server.mjs +493 -106
- package/dist/tasks-CnMLpfk-.d.ts +274 -0
- package/dist/types-BQDlIvfS.d.ts +34 -0
- package/dist/{types-BV3nAKTL.d.ts → types-Bfhhnh3G.d.ts} +23 -1
- package/dist/types-D5OwhtsQ.d.ts +97 -0
- package/dist/vector/hnsw-build-worker.d.ts +2 -7
- package/dist/vector/hnsw-build-worker.mjs +2 -1
- package/dist/vector/search-worker.d.ts +373 -0
- package/dist/vector/search-worker.mjs +279 -0
- package/dist/workers/entry.mjs +43 -25
- package/package.json +42 -2
- package/dist/chunk-FKK76OR7.mjs +0 -456
- package/dist/chunk-RQLXC2YS.mjs +0 -269
- package/dist/direct-executor-3W4QRA4E.mjs +0 -5
package/README.md
CHANGED
|
@@ -12,11 +12,11 @@ Distributed search, reforged.
|
|
|
12
12
|
|
|
13
13
|
Narsil is a distributed search engine with full-text, vector, hybrid, and geosearch. One codebase runs in two contexts: embedded in your application process, where queries answer without a network hop, and as a standalone search server with a REST API, a write-ahead log, and bulk NDJSON ingest. Both contexts run the same engine and store indexes in the same cross-language binary format (.nrsl), so an index built in one loads in the other.
|
|
14
14
|
|
|
15
|
-
The engine partitions large indexes across workers and merges partition results into a single ranked answer. Its BM25 ranking matches the Anserini reference within 0.
|
|
15
|
+
The engine partitions large indexes across workers and merges partition results into a single ranked answer. Its BM25 ranking matches the Anserini reference within 0.006 nDCG@10 on the BEIR datasets. On BEIR SciFact it takes the top nDCG@10 at 0.681, narrowly ahead of Elasticsearch and OpenSearch at 0.679, and answers 958 keyword queries per second against their 841 and 878 ([benchmarks](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md)). This TypeScript package is the reference implementation of the cross-language `.nrsl` format, and a second-language port in Go or Rust is the headline item on the [roadmap](https://github.com/assetcorp/narsil/blob/main/ROADMAP.md).
|
|
16
16
|
|
|
17
17
|
Try it in your browser at [narsil.sondelali.com/demo](https://narsil.sondelali.com/demo). Read the full documentation at [narsil.sondelali.com/docs](https://narsil.sondelali.com/docs).
|
|
18
18
|
|
|
19
|
-
> *narsil* is the sword of Elendil in Tolkien's Lord of the Rings, shattered into shards and later reforged. The name maps to the architecture: data shatters into partitions, each shard
|
|
19
|
+
> *narsil* is the sword of Elendil in Tolkien's Lord of the Rings, shattered into shards and later reforged. The name maps to the architecture: data shatters into partitions, the engine persists each shard on its own, and every query reforges them into one ranked answer.
|
|
20
20
|
|
|
21
21
|
## Contents
|
|
22
22
|
|
|
@@ -79,7 +79,7 @@ const results = await narsil.query('products', {
|
|
|
79
79
|
})
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
Every hit
|
|
82
|
+
Every hit holds the document, its id, and its BM25 score. `results.count` reports how many documents matched in total, and `results.elapsed` reports the query time in milliseconds.
|
|
83
83
|
|
|
84
84
|
## Features
|
|
85
85
|
|
|
@@ -93,7 +93,7 @@ Every hit carries the document, its id, and its BM25 score. `results.count` repo
|
|
|
93
93
|
|
|
94
94
|
**Scale.** [Partitioned indexes](https://github.com/assetcorp/narsil/blob/main/docs/partitions-and-workers.md) route documents by deterministic hash and reshape online through `rebalance()`, with writes buffering in a write-ahead queue during the reshape. Worker promotion moves search off the main thread once document counts cross a threshold.
|
|
95
95
|
|
|
96
|
-
**Operations.** The [HTTP server](https://github.com/assetcorp/narsil/blob/main/docs/http-server.md) subpath wraps an engine in a REST API with health probes, bulk NDJSON import, snapshot and restore endpoints, and task-based long operations. [Events, plugins, and memory reporting](https://github.com/assetcorp/narsil/blob/main/docs/observability.md) cover observability, and [language modules](https://github.com/assetcorp/narsil/blob/main/docs/language-support.md) cover 107 languages as separate entry points, 20 of them African.
|
|
96
|
+
**Operations.** The [HTTP server](https://github.com/assetcorp/narsil/blob/main/docs/http-server.md) subpath wraps an engine in a REST API with health probes, bulk NDJSON import, snapshot and restore endpoints, and task-based long operations. The [client](https://github.com/assetcorp/narsil/blob/main/docs/client.md) subpath reaches every one of those routes from a browser or from Node under the engine's own method names, and the [React](https://github.com/assetcorp/narsil/blob/main/docs/react.md) subpath gives those methods to components as hooks. [Events, plugins, and memory reporting](https://github.com/assetcorp/narsil/blob/main/docs/observability.md) cover observability, and [language modules](https://github.com/assetcorp/narsil/blob/main/docs/language-support.md) cover 107 languages as separate entry points, 20 of them African.
|
|
97
97
|
|
|
98
98
|
## Documentation
|
|
99
99
|
|
|
@@ -110,7 +110,10 @@ Every hit carries the document, its id, and its BM25 score. `results.count` repo
|
|
|
110
110
|
| [Persistence and durability](../../docs/persistence-and-durability.md) | Storage backends, the write-ahead log, checkpoints, recovery, and snapshots |
|
|
111
111
|
| [Partitions and workers](../../docs/partitions-and-workers.md) | Partition routing, online rebalancing, worker promotion, and multi-instance invalidation |
|
|
112
112
|
| [Language support](../../docs/language-support.md) | The 107 language modules, analysis revisions and rebuilds, and named tokenizers and stop words |
|
|
113
|
-
| [HTTP server](../../docs/http-server.md) | Wrapping an engine in a REST API,
|
|
113
|
+
| [HTTP server](../../docs/http-server.md) | Wrapping an engine in a REST API, every route it serves, and long-running tasks |
|
|
114
|
+
| [Cluster mode](../../docs/cluster.md) | Multi-node indexes: nodes and roles, replication, routed writes, distributed searches and reads, and what a cluster refuses |
|
|
115
|
+
| [Client](../../docs/client.md) | Reaching a server from a browser or Node, following a task, and the codes it raises |
|
|
116
|
+
| [React](../../docs/react.md) | The hooks over the client, one shared request per key, and loading a corpus from a component |
|
|
114
117
|
| [Observability](../../docs/observability.md) | Plugin hooks, engine events, and memory reporting |
|
|
115
118
|
| [Errors](../../docs/errors.md) | Every error code and what throws it |
|
|
116
119
|
|
|
@@ -122,15 +125,15 @@ The [specification](../spec/) defines the `.nrsl` format, the analysis pipeline,
|
|
|
122
125
|
| --- | --- |
|
|
123
126
|
| [HTTP server](examples/http-server/README.md) | The launcher runs the engine as a REST service with durability, API-key auth, and Docker packaging, and its README documents the full API surface. |
|
|
124
127
|
| [Browser](examples/browser/README.md) | The app embeds the engine in a browser with IndexedDB persistence and Web Worker search. |
|
|
125
|
-
| [Server app](examples/server-app/README.md) | The app
|
|
128
|
+
| [Server app](examples/server-app/README.md) | The app reaches the HTTP server through the client SDK and the React hooks, loads corpora as import tasks, and answers questions from them in an Ask view. |
|
|
126
129
|
|
|
127
130
|
## Distribution
|
|
128
131
|
|
|
129
|
-
`@delali/narsil/distribution` holds
|
|
132
|
+
`@delali/narsil/distribution` holds Narsil's multi-node cluster mode: nodes and roles, replication, coordinator adapters for etcd and in-process testing, TCP and gRPC transports with mutual TLS, and distributed query routing. A cluster node creates, drops, clears, writes, updates, searches, lists, counts, and suggests across every partition, and the [cluster example](examples/cluster) runs three node processes against etcd and survives a kill. The layer is experimental and its APIs change without notice, so pin an exact version before you depend on it. The [cluster guide](../../docs/cluster.md) covers the surface, and [`packages/spec/distribution`](../spec/distribution) specifies the contract every implementation follows.
|
|
130
133
|
|
|
131
134
|
## Search quality
|
|
132
135
|
|
|
133
|
-
Ranking quality is measured against the [BEIR](https://github.com/beir-cellar/beir) SciFact corpus, 5,183 documents with 300 judged queries, where a human relevance judgment scores each query-document pair. Narsil runs in one process against Orama and MiniSearch, and every engine uses identical stop words (Lucene English,
|
|
136
|
+
Ranking quality is measured against the [BEIR](https://github.com/beir-cellar/beir) SciFact corpus, 5,183 documents with 300 judged queries, where a human relevance judgment scores each query-document pair. Narsil runs in one process against Orama and MiniSearch, and every engine uses identical stop words (Lucene English, 33 terms) and default BM25 parameters, while each one stems English with its own implementation. Narsil takes the top nDCG@10 of the three.
|
|
134
137
|
|
|
135
138
|
**What these metrics mean:**
|
|
136
139
|
|
|
@@ -154,7 +157,7 @@ Narsil also runs as a search server. On the BEIR information-retrieval datasets
|
|
|
154
157
|
| Deno | Web Workers | Filesystem | BroadcastChannel |
|
|
155
158
|
| Browser | Web Workers | IndexedDB | BroadcastChannel |
|
|
156
159
|
|
|
157
|
-
The [browser example](examples/browser/README.md) shows an embedded engine with IndexedDB persistence, and the [server app example](examples/server-app/README.md) shows
|
|
160
|
+
The [browser example](examples/browser/README.md) shows an embedded engine with IndexedDB persistence, and the [server app example](examples/server-app/README.md) shows the same UI over the client SDK and the React hooks.
|
|
158
161
|
|
|
159
162
|
## License
|
|
160
163
|
|
|
@@ -146,4 +146,4 @@ interface EmbeddingAdapter {
|
|
|
146
146
|
shutdown?(): Promise<void>;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
export type { EmbeddingAdapter as E, InvalidationAdapter as I,
|
|
149
|
+
export type { EmbeddingAdapter as E, InvalidationAdapter as I, PersistenceAdapter as P, InvalidationEvent as a, PartitionStatistics as b };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// src/core/ordering/code-points.ts
|
|
2
|
+
function adjustUtf16Unit(unit) {
|
|
3
|
+
if (unit < 55296) return unit;
|
|
4
|
+
if (unit < 57344) return unit + 8192;
|
|
5
|
+
return unit - 2048;
|
|
6
|
+
}
|
|
7
|
+
function compareCodePoints(a, b) {
|
|
8
|
+
const shorter = a.length < b.length ? a.length : b.length;
|
|
9
|
+
let i = 0;
|
|
10
|
+
while (i < shorter && a.charCodeAt(i) === b.charCodeAt(i)) i++;
|
|
11
|
+
if (i === shorter) return a.length - b.length;
|
|
12
|
+
return adjustUtf16Unit(a.charCodeAt(i)) - adjustUtf16Unit(b.charCodeAt(i));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/core/ordering/fold-table.ts
|
|
16
|
+
var SINGLE_FOLDS = "1t,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;2j,lj;b,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;2,w;1,w;1,w;1,w;1,w;1,w;1,w;y,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;4,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-3d;1,1;2,1;2,1;2,-7g;2,5u;1,1;2,1;2,5q;1,1;2,5p;1,5p;1,1;3,27;1,5m;1,5n;1,1;2,5p;1,5r;2,5v;1,5t;1,1;4,5v;1,5x;2,5y;1,1;2,1;2,1;2,62;1,1;2,62;3,1;2,62;1,1;2,61;1,61;1,1;2,1;2,63;1,1;4,1;8,2;1,1;2,2;1,1;2,2;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,2;1,1;2,1;2,-2p;1,-1k;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-3m;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;8,8bv;1,1;2,-4j;1,8bs;3,1;2,-5f;1,1x;1,1z;1,1;2,1;2,1;2,1;2,1;6v,38;17,1;2,1;4,1;9,38;7,12;2,11;1,11;1,11;2,1s;2,1r;1,1r;2,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;2,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;n,1;d,8;1,-u;1,-p;4,-f;1,-m;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-1i;1,-1c;3,-1o;1,-1s;2,1;2,-7;1,1;3,-3m;1,-3m;1,-3m;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1d,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;a,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,f;1,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;28a,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;2,5ls;6,5ls;mj,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1oj,-4su;1,-4st;1,-4sk;1,-4si;1,-4si;1,-4sj;1,-4sc;1,-4ro;1,r7n;1,1;7,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;3,-2bk;1,-2bk;1,-2bk;8x,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;7,-1m;5,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;a,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;b,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;c,-8;2,-8;2,-8;2,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;21,-8;1,-8;1,-22;1,-22;3,-5j9;a,-2e;1,-2e;1,-2e;1,-2e;d,-8;1,-8;1,-2s;1,-2s;d,-8;1,-8;1,-34;1,-34;1,-7;c,-3k;1,-3k;1,-3i;1,-3i;8b,-5st;4,-6gv;1,-6di;7,s;1a,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;k,1;mr,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1f5,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1d,1;2,-8af;1,-2xy;1,-89z;3,1;2,1;2,1;2,-8bg;1,-8al;1,-8bj;1,-8bi;2,1;3,1;9,-8cf;1,-8cf;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;9,1;2,1;5,1;nym,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;k,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3s,1;2,1;2,1;2,1;2,1;2,1;2,1;4,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;b,1;2,1;2,-r9g;1,1;2,1;2,1;2,1;2,1;5,1;2,-wmg;3,1;2,1;4,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-wn8;1,-wnj;1,-wnf;1,-wn5;1,-wn8;2,-wlu;1,-wmi;1,-wlx;1,ps;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-1c;1,-wn7;1,-raw;1,1;2,1;2,-wo7;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-wu9;p,1;or,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;ggy,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;xy,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;3t,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;4d,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;2,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;2,13;1,13;1,13;1,13;1,13;1,13;1,13;2,13;1,13;1d7,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;4e,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;27v,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;gw1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1t,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;o5k,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;";
|
|
17
|
+
var MULTI_FOLDS = "67,37,37;29,2x,lj;p,jg,32;4n,2y,lo;bk,qh,lk,ld;w,qt,lk,ld;d3,12d,136;4y7,2w,mp;1,38,lk;1,3b,lm;1,3d,lm;1,2p,ji;4,37,37;4y,qt,lv;2,qt,lv,lc;2,qt,lv,ld;2,qt,lv,n6;16,64g,qh;1,64h,qh;1,64i,qh;1,64j,qh;1,64k,qh;1,64l,qh;1,64m,qh;1,64n,qh;1,64g,qh;1,64h,qh;1,64i,qh;1,64j,qh;1,64k,qh;1,64l,qh;1,64m,qh;1,64n,qh;1,65c,qh;1,65d,qh;1,65e,qh;1,65f,qh;1,65g,qh;1,65h,qh;1,65i,qh;1,65j,qh;1,65c,qh;1,65d,qh;1,65e,qh;1,65f,qh;1,65g,qh;1,65h,qh;1,65i,qh;1,65j,qh;1,674,qh;1,675,qh;1,676,qh;1,677,qh;1,678,qh;1,679,qh;1,67a,qh;1,67b,qh;1,674,qh;1,675,qh;1,676,qh;1,677,qh;1,678,qh;1,679,qh;1,67a,qh;1,67b,qh;3,67k,qh;1,q9,qh;1,q4,qh;2,q9,n6;1,q9,n6,qh;5,q9,qh;6,67o,qh;1,qf,qh;1,q6,qh;2,qf,n6;1,qf,n6,qh;5,qf,qh;6,qh,lk,lc;1,qh,lk,ld;3,qh,n6;1,qh,lk,n6;b,qt,lk,lc;1,qt,lk,ld;1,qp,lv;2,qt,n6;1,qt,lk,n6;b,67w,qh;1,qx,qh;1,r2,qh;2,qx,n6;1,qx,n6,qh;5,qx,qh;179g,2u,2u;1,2u,2x;1,2u,30;1,2u,2u,2x;1,2u,2u,30;1,37,38;1,37,38;d,12s,12u;1,12s,12d;1,12s,12j;1,132,12u;1,12s,12l;";
|
|
18
|
+
var singleTable = null;
|
|
19
|
+
var multiTable = null;
|
|
20
|
+
function singleFoldTable() {
|
|
21
|
+
if (singleTable === null) {
|
|
22
|
+
singleTable = /* @__PURE__ */ new Map();
|
|
23
|
+
let source = 0;
|
|
24
|
+
for (const entry of SINGLE_FOLDS.split(";")) {
|
|
25
|
+
if (entry.length === 0) continue;
|
|
26
|
+
const [delta, offset] = entry.split(",");
|
|
27
|
+
source += Number.parseInt(delta, 36);
|
|
28
|
+
singleTable.set(source, source + Number.parseInt(offset, 36));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return singleTable;
|
|
32
|
+
}
|
|
33
|
+
function multiFoldTable() {
|
|
34
|
+
if (multiTable === null) {
|
|
35
|
+
multiTable = /* @__PURE__ */ new Map();
|
|
36
|
+
let source = 0;
|
|
37
|
+
for (const entry of MULTI_FOLDS.split(";")) {
|
|
38
|
+
if (entry.length === 0) continue;
|
|
39
|
+
const parts = entry.split(",");
|
|
40
|
+
source += Number.parseInt(parts[0], 36);
|
|
41
|
+
multiTable.set(
|
|
42
|
+
source,
|
|
43
|
+
parts.slice(1).map((cp) => Number.parseInt(cp, 36))
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return multiTable;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/core/ordering/fold-compare.ts
|
|
51
|
+
var EXHAUSTED = -1;
|
|
52
|
+
function nextFoldedCodePoint(text, cursor, single, multi) {
|
|
53
|
+
if (cursor.pending !== null) {
|
|
54
|
+
const cp2 = cursor.pending[cursor.pendingIndex];
|
|
55
|
+
cursor.pendingIndex++;
|
|
56
|
+
if (cursor.pendingIndex === cursor.pending.length) {
|
|
57
|
+
cursor.pending = null;
|
|
58
|
+
cursor.pendingIndex = 0;
|
|
59
|
+
}
|
|
60
|
+
return cp2;
|
|
61
|
+
}
|
|
62
|
+
if (cursor.index >= text.length) return EXHAUSTED;
|
|
63
|
+
let cp = text.charCodeAt(cursor.index);
|
|
64
|
+
cursor.index++;
|
|
65
|
+
if (cp < 128) {
|
|
66
|
+
return cp >= 65 && cp <= 90 ? cp + 32 : cp;
|
|
67
|
+
}
|
|
68
|
+
if (cp >= 55296 && cp < 56320 && cursor.index < text.length) {
|
|
69
|
+
const low = text.charCodeAt(cursor.index);
|
|
70
|
+
if (low >= 56320 && low < 57344) {
|
|
71
|
+
cp = 65536 + (cp - 55296 << 10) + (low - 56320);
|
|
72
|
+
cursor.index++;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const mapped = single.get(cp);
|
|
76
|
+
if (mapped !== void 0) return mapped;
|
|
77
|
+
const expansion = multi.get(cp);
|
|
78
|
+
if (expansion === void 0) return cp;
|
|
79
|
+
if (expansion.length > 1) {
|
|
80
|
+
cursor.pending = expansion;
|
|
81
|
+
cursor.pendingIndex = 1;
|
|
82
|
+
}
|
|
83
|
+
return expansion[0];
|
|
84
|
+
}
|
|
85
|
+
function compareCaseFolded(a, b) {
|
|
86
|
+
const shorter = a.length < b.length ? a.length : b.length;
|
|
87
|
+
let start = 0;
|
|
88
|
+
while (start < shorter && a.charCodeAt(start) === b.charCodeAt(start)) start++;
|
|
89
|
+
if (start === a.length && start === b.length) return 0;
|
|
90
|
+
if (start > 0) {
|
|
91
|
+
const previous = a.charCodeAt(start - 1);
|
|
92
|
+
if (previous >= 55296 && previous < 56320) start--;
|
|
93
|
+
}
|
|
94
|
+
const single = singleFoldTable();
|
|
95
|
+
const multi = multiFoldTable();
|
|
96
|
+
const aCursor = { index: start, pending: null, pendingIndex: 0 };
|
|
97
|
+
const bCursor = { index: start, pending: null, pendingIndex: 0 };
|
|
98
|
+
for (; ; ) {
|
|
99
|
+
const aCp = nextFoldedCodePoint(a, aCursor, single, multi);
|
|
100
|
+
const bCp = nextFoldedCodePoint(b, bCursor, single, multi);
|
|
101
|
+
if (aCp !== bCp) return aCp - bCp;
|
|
102
|
+
if (aCp === EXHAUSTED) return 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function compareSortStrings(a, b) {
|
|
106
|
+
const folded = compareCaseFolded(a, b);
|
|
107
|
+
if (folded !== 0) return folded;
|
|
108
|
+
return compareCodePoints(a, b);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/core/ordering/sort-values.ts
|
|
112
|
+
var SORT_VALUE_MAX_CODE_POINTS = 512;
|
|
113
|
+
function truncateSortString(value) {
|
|
114
|
+
if (value.length <= SORT_VALUE_MAX_CODE_POINTS) return value;
|
|
115
|
+
let index = 0;
|
|
116
|
+
let counted = 0;
|
|
117
|
+
while (index < value.length && counted < SORT_VALUE_MAX_CODE_POINTS) {
|
|
118
|
+
const unit = value.charCodeAt(index);
|
|
119
|
+
if (unit >= 55296 && unit < 56320 && index + 1 < value.length) {
|
|
120
|
+
const low = value.charCodeAt(index + 1);
|
|
121
|
+
if (low >= 56320 && low < 57344) index++;
|
|
122
|
+
}
|
|
123
|
+
index++;
|
|
124
|
+
counted++;
|
|
125
|
+
}
|
|
126
|
+
return value.slice(0, index);
|
|
127
|
+
}
|
|
128
|
+
function toComparableSortValue(value) {
|
|
129
|
+
if (typeof value === "string") return truncateSortString(value);
|
|
130
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
131
|
+
if (typeof value === "boolean") return value;
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
function readSortField(document, path) {
|
|
135
|
+
const segments = path.split(".");
|
|
136
|
+
let current = document;
|
|
137
|
+
for (const segment of segments) {
|
|
138
|
+
if (current === null || current === void 0 || typeof current !== "object") return void 0;
|
|
139
|
+
if (!Object.hasOwn(current, segment)) return void 0;
|
|
140
|
+
current = current[segment];
|
|
141
|
+
}
|
|
142
|
+
return current;
|
|
143
|
+
}
|
|
144
|
+
function typeRank(value) {
|
|
145
|
+
if (typeof value === "number") return 0;
|
|
146
|
+
if (typeof value === "string") return 1;
|
|
147
|
+
return 2;
|
|
148
|
+
}
|
|
149
|
+
function comparePresentValues(a, b) {
|
|
150
|
+
const rankDifference = typeRank(a) - typeRank(b);
|
|
151
|
+
if (rankDifference !== 0) return rankDifference;
|
|
152
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
153
|
+
if (typeof a === "string" && typeof b === "string") return compareSortStrings(a, b);
|
|
154
|
+
if (a === b) return 0;
|
|
155
|
+
return a ? 1 : -1;
|
|
156
|
+
}
|
|
157
|
+
function compareComparableValues(a, b, direction) {
|
|
158
|
+
if (a === null && b === null) return 0;
|
|
159
|
+
if (a === null) return 1;
|
|
160
|
+
if (b === null) return -1;
|
|
161
|
+
const comparison = comparePresentValues(a, b);
|
|
162
|
+
if (comparison === 0) return 0;
|
|
163
|
+
return direction === "desc" ? -comparison : comparison;
|
|
164
|
+
}
|
|
165
|
+
function compareComparableKeys(aKey, bKey, directions) {
|
|
166
|
+
for (let i = 0; i < directions.length; i++) {
|
|
167
|
+
const comparison = compareComparableValues(aKey[i] ?? null, bKey[i] ?? null, directions[i]);
|
|
168
|
+
if (comparison !== 0) return comparison;
|
|
169
|
+
}
|
|
170
|
+
return 0;
|
|
171
|
+
}
|
|
172
|
+
function compareSortValues(aValues, bValues, directions) {
|
|
173
|
+
for (let i = 0; i < directions.length; i++) {
|
|
174
|
+
const a = toComparableSortValue(aValues[i]);
|
|
175
|
+
const b = toComparableSortValue(bValues[i]);
|
|
176
|
+
if (a === null && b === null) continue;
|
|
177
|
+
if (a === null) return 1;
|
|
178
|
+
if (b === null) return -1;
|
|
179
|
+
const comparison = comparePresentValues(a, b);
|
|
180
|
+
if (comparison !== 0) return directions[i] === "desc" ? -comparison : comparison;
|
|
181
|
+
}
|
|
182
|
+
return 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { SORT_VALUE_MAX_CODE_POINTS, compareCodePoints, compareComparableKeys, compareComparableValues, compareSortValues, readSortField, toComparableSortValue };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// src/distribution/transport/types.ts
|
|
2
|
+
var DEFAULT_TRANSPORT_CONFIG = {
|
|
3
|
+
connectTimeout: 5e3,
|
|
4
|
+
requestTimeout: 3e4,
|
|
5
|
+
replicationTimeout: 1e4,
|
|
6
|
+
snapshotTimeout: 3e5
|
|
7
|
+
};
|
|
8
|
+
var MAX_MESSAGE_SIZE_BYTES = 67108864;
|
|
9
|
+
var TransportErrorCodes = {
|
|
10
|
+
CONNECT_FAILED: "TRANSPORT_CONNECT_FAILED",
|
|
11
|
+
TIMEOUT: "TRANSPORT_TIMEOUT",
|
|
12
|
+
MESSAGE_TOO_LARGE: "TRANSPORT_MESSAGE_TOO_LARGE",
|
|
13
|
+
DECODE_FAILED: "TRANSPORT_DECODE_FAILED",
|
|
14
|
+
PEER_UNAVAILABLE: "TRANSPORT_PEER_UNAVAILABLE"
|
|
15
|
+
};
|
|
16
|
+
var TransportError = class extends Error {
|
|
17
|
+
code;
|
|
18
|
+
details;
|
|
19
|
+
constructor(code, message, details) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "TransportError";
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.details = details ?? {};
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var ReplicationMessageTypes = {
|
|
27
|
+
FORWARD: "replication.forward",
|
|
28
|
+
FORWARD_BATCH: "replication.forward_batch",
|
|
29
|
+
ENTRY: "replication.entry",
|
|
30
|
+
ENTRY_BATCH: "replication.entry_batch",
|
|
31
|
+
ACK: "replication.ack",
|
|
32
|
+
SYNC_REQUEST: "replication.sync_request",
|
|
33
|
+
SYNC_ENTRIES: "replication.sync_entries",
|
|
34
|
+
SNAPSHOT_START: "replication.snapshot_start",
|
|
35
|
+
SNAPSHOT_CHUNK: "replication.snapshot_chunk",
|
|
36
|
+
SNAPSHOT_END: "replication.snapshot_end",
|
|
37
|
+
SNAPSHOT_SYNC_REQUEST: "replication.snapshot_sync_request",
|
|
38
|
+
INSYNC_REMOVE: "replication.insync_remove",
|
|
39
|
+
INSYNC_CONFIRM: "replication.insync_confirm"
|
|
40
|
+
};
|
|
41
|
+
var QueryMessageTypes = {
|
|
42
|
+
SEARCH: "query.search",
|
|
43
|
+
SEARCH_RESULT: "query.search_result",
|
|
44
|
+
FETCH: "query.fetch",
|
|
45
|
+
FETCH_RESULT: "query.fetch_result",
|
|
46
|
+
STATS: "query.stats",
|
|
47
|
+
STATS_RESULT: "query.stats_result",
|
|
48
|
+
COUNT: "query.count",
|
|
49
|
+
COUNT_RESULT: "query.count_result",
|
|
50
|
+
LIST: "query.list",
|
|
51
|
+
LIST_RESULT: "query.list_result",
|
|
52
|
+
SUGGEST: "query.suggest",
|
|
53
|
+
SUGGEST_RESULT: "query.suggest_result",
|
|
54
|
+
PREFLIGHT: "query.preflight",
|
|
55
|
+
PREFLIGHT_RESULT: "query.preflight_result"
|
|
56
|
+
};
|
|
57
|
+
var ClusterMessageTypes = {
|
|
58
|
+
PING: "cluster.ping",
|
|
59
|
+
PONG: "cluster.pong",
|
|
60
|
+
BOOTSTRAP_COMPLETE: "cluster.bootstrap_complete"
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export { ClusterMessageTypes, DEFAULT_TRANSPORT_CONFIG, MAX_MESSAGE_SIZE_BYTES, QueryMessageTypes, ReplicationMessageTypes, TransportError, TransportErrorCodes };
|
|
@@ -10,6 +10,7 @@ var ErrorCodes = {
|
|
|
10
10
|
DOC_VALIDATION_FAILED: "DOC_VALIDATION_FAILED",
|
|
11
11
|
INDEX_NOT_FOUND: "INDEX_NOT_FOUND",
|
|
12
12
|
INDEX_ALREADY_EXISTS: "INDEX_ALREADY_EXISTS",
|
|
13
|
+
INDEX_ORPHANED: "INDEX_ORPHANED",
|
|
13
14
|
PARTITION_CORRUPTED: "PARTITION_CORRUPTED",
|
|
14
15
|
PARTITION_REBALANCING_BACKPRESSURE: "PARTITION_REBALANCING_BACKPRESSURE",
|
|
15
16
|
WORKER_CRASHED: "WORKER_CRASHED",
|
|
@@ -27,6 +28,7 @@ var ErrorCodes = {
|
|
|
27
28
|
SEARCH_INVALID_FILTER: "SEARCH_INVALID_FILTER",
|
|
28
29
|
SEARCH_INVALID_MODE: "SEARCH_INVALID_MODE",
|
|
29
30
|
SEARCH_INVALID_CURSOR: "SEARCH_INVALID_CURSOR",
|
|
31
|
+
SEARCH_RESULT_WINDOW_EXCEEDED: "SEARCH_RESULT_WINDOW_EXCEEDED",
|
|
30
32
|
LANGUAGE_NOT_SUPPORTED: "LANGUAGE_NOT_SUPPORTED",
|
|
31
33
|
ENVELOPE_VERSION_MISMATCH: "ENVELOPE_VERSION_MISMATCH",
|
|
32
34
|
ENVELOPE_INVALID_MAGIC: "ENVELOPE_INVALID_MAGIC",
|
|
@@ -41,6 +43,7 @@ var ErrorCodes = {
|
|
|
41
43
|
QUERY_PARTIAL_FAILURE: "QUERY_PARTIAL_FAILURE",
|
|
42
44
|
QUERY_NODE_TIMEOUT: "QUERY_NODE_TIMEOUT",
|
|
43
45
|
QUERY_NO_ACTIVE_REPLICA: "QUERY_NO_ACTIVE_REPLICA",
|
|
46
|
+
CLUSTER_OPERATION_UNSUPPORTED: "CLUSTER_OPERATION_UNSUPPORTED",
|
|
44
47
|
ALLOCATION_NO_DATA_NODES: "ALLOCATION_NO_DATA_NODES",
|
|
45
48
|
ALLOCATION_INVALID_CONFIG: "ALLOCATION_INVALID_CONFIG",
|
|
46
49
|
ALLOCATION_FAILED: "ALLOCATION_FAILED",
|
|
@@ -51,6 +54,7 @@ var ErrorCodes = {
|
|
|
51
54
|
NODE_ALREADY_JOINED: "NODE_ALREADY_JOINED",
|
|
52
55
|
NODE_NOT_JOINED: "NODE_NOT_JOINED",
|
|
53
56
|
COORDINATOR_DEPENDENCY_MISSING: "COORDINATOR_DEPENDENCY_MISSING",
|
|
57
|
+
TRANSPORT_DEPENDENCY_MISSING: "TRANSPORT_DEPENDENCY_MISSING",
|
|
54
58
|
REPLICATION_ENTRY_INVALID: "REPLICATION_ENTRY_INVALID",
|
|
55
59
|
REPLICATION_INSYNC_REMOVAL_FAILED: "REPLICATION_INSYNC_REMOVAL_FAILED",
|
|
56
60
|
REPLICATION_ROLLBACK_FAILED: "REPLICATION_ROLLBACK_FAILED",
|
|
@@ -89,6 +93,27 @@ var ErrorCodes = {
|
|
|
89
93
|
SNAPSHOT_SYNC_NOT_ASSIGNED: "SNAPSHOT_SYNC_NOT_ASSIGNED",
|
|
90
94
|
SNAPSHOT_SYNC_ABORTED: "SNAPSHOT_SYNC_ABORTED"
|
|
91
95
|
};
|
|
96
|
+
var ServerErrorCodes = {
|
|
97
|
+
INVALID_REQUEST: "INVALID_REQUEST",
|
|
98
|
+
INVALID_JSON: "INVALID_JSON",
|
|
99
|
+
EMPTY_BODY: "EMPTY_BODY",
|
|
100
|
+
PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE",
|
|
101
|
+
NOT_FOUND: "NOT_FOUND",
|
|
102
|
+
TASK_NOT_FOUND: "TASK_NOT_FOUND",
|
|
103
|
+
TASK_NOT_CANCELLABLE: "TASK_NOT_CANCELLABLE",
|
|
104
|
+
TASK_OWNED_BY_ANOTHER_INSTANCE: "TASK_OWNED_BY_ANOTHER_INSTANCE",
|
|
105
|
+
TOO_MANY_REQUESTS: "TOO_MANY_REQUESTS",
|
|
106
|
+
HOOK_ERROR: "HOOK_ERROR",
|
|
107
|
+
INTERNAL_ERROR: "INTERNAL_ERROR"
|
|
108
|
+
};
|
|
109
|
+
var ClientErrorCodes = {
|
|
110
|
+
CLIENT_CONNECTION_FAILED: "CLIENT_CONNECTION_FAILED",
|
|
111
|
+
CLIENT_REQUEST_TIMEOUT: "CLIENT_REQUEST_TIMEOUT",
|
|
112
|
+
CLIENT_REQUEST_ABORTED: "CLIENT_REQUEST_ABORTED",
|
|
113
|
+
CLIENT_INVALID_RESPONSE: "CLIENT_INVALID_RESPONSE",
|
|
114
|
+
CLIENT_TASK_TIMEOUT: "CLIENT_TASK_TIMEOUT",
|
|
115
|
+
CLIENT_UNEXPECTED_ERROR: "CLIENT_UNEXPECTED_ERROR"
|
|
116
|
+
};
|
|
92
117
|
var NarsilError = class extends Error {
|
|
93
118
|
/** This says which failure it is. */
|
|
94
119
|
code;
|
|
@@ -97,7 +122,10 @@ var NarsilError = class extends Error {
|
|
|
97
122
|
/**
|
|
98
123
|
* Builds an error carrying a code the caller can branch on.
|
|
99
124
|
*
|
|
100
|
-
* @param code - The failure this error reports
|
|
125
|
+
* @param code - The failure this error reports, from {@link ErrorCodes} for
|
|
126
|
+
* an engine failure, {@link ServerErrorCodes} for one the HTTP layer raised,
|
|
127
|
+
* or {@link ClientErrorCodes} for one that stopped a request from reaching a
|
|
128
|
+
* server.
|
|
101
129
|
* @param message - Plain description, for a log or a person.
|
|
102
130
|
* @param details - Values behind the failure, which reach
|
|
103
131
|
* {@link NarsilError.details}.
|
|
@@ -112,5 +140,8 @@ var NarsilError = class extends Error {
|
|
|
112
140
|
function createNarsilError(code, message, details) {
|
|
113
141
|
return new NarsilError(code, message, details);
|
|
114
142
|
}
|
|
143
|
+
function describeError(error) {
|
|
144
|
+
return error instanceof Error ? error.message : String(error);
|
|
145
|
+
}
|
|
115
146
|
|
|
116
|
-
export { ErrorCodes, NarsilError, createNarsilError };
|
|
147
|
+
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, createNarsilError, describeError };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { MAX_MESSAGE_SIZE_BYTES, TransportError, TransportErrorCodes } from './chunk-C6VVLMRX.mjs';
|
|
2
|
+
import { encode, decode } from '@msgpack/msgpack';
|
|
3
|
+
|
|
4
|
+
// src/distribution/transport/tcp/types.ts
|
|
5
|
+
var DEFAULT_TCP_CONFIG = {
|
|
6
|
+
host: "0.0.0.0",
|
|
7
|
+
port: 9300,
|
|
8
|
+
connectTimeout: 5e3,
|
|
9
|
+
requestTimeout: 3e4,
|
|
10
|
+
replicationTimeout: 1e4,
|
|
11
|
+
snapshotTimeout: 3e5,
|
|
12
|
+
maxConnections: 256
|
|
13
|
+
};
|
|
14
|
+
var LENGTH_PREFIX_BYTES = 4;
|
|
15
|
+
var FRAME_TYPE_REQUEST = 1;
|
|
16
|
+
var FRAME_TYPE_RESPONSE = 2;
|
|
17
|
+
var FRAME_TYPE_STREAM_CHUNK = 3;
|
|
18
|
+
var FRAME_TYPE_STREAM_END = 4;
|
|
19
|
+
function encodeFrame(frameType, requestId, data) {
|
|
20
|
+
const envelope = encode({ frameType, requestId, data });
|
|
21
|
+
const totalLength = envelope.byteLength;
|
|
22
|
+
if (totalLength > MAX_MESSAGE_SIZE_BYTES) {
|
|
23
|
+
throw new TransportError(
|
|
24
|
+
TransportErrorCodes.MESSAGE_TOO_LARGE,
|
|
25
|
+
`Encoded frame (${totalLength} bytes) exceeds the ${MAX_MESSAGE_SIZE_BYTES} byte limit`,
|
|
26
|
+
{ payloadSize: totalLength }
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const buffer = new Uint8Array(LENGTH_PREFIX_BYTES + totalLength);
|
|
30
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
31
|
+
view.setUint32(0, totalLength, false);
|
|
32
|
+
buffer.set(envelope, LENGTH_PREFIX_BYTES);
|
|
33
|
+
return buffer;
|
|
34
|
+
}
|
|
35
|
+
function encodeTransportMessage(message) {
|
|
36
|
+
return new Uint8Array(
|
|
37
|
+
encode({
|
|
38
|
+
type: message.type,
|
|
39
|
+
sourceId: message.sourceId,
|
|
40
|
+
requestId: message.requestId,
|
|
41
|
+
payload: message.payload
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
function decodeTransportMessage(data) {
|
|
46
|
+
const decoded = decode(data);
|
|
47
|
+
return {
|
|
48
|
+
type: decoded.type,
|
|
49
|
+
sourceId: decoded.sourceId,
|
|
50
|
+
requestId: decoded.requestId,
|
|
51
|
+
payload: new Uint8Array(decoded.payload)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
var BUFFER_LIMIT = MAX_MESSAGE_SIZE_BYTES + LENGTH_PREFIX_BYTES;
|
|
55
|
+
var FrameParser = class {
|
|
56
|
+
chunks = [];
|
|
57
|
+
totalLength = 0;
|
|
58
|
+
onFrame;
|
|
59
|
+
constructor(onFrame) {
|
|
60
|
+
this.onFrame = onFrame;
|
|
61
|
+
}
|
|
62
|
+
feed(data) {
|
|
63
|
+
this.totalLength += data.byteLength;
|
|
64
|
+
if (this.totalLength > BUFFER_LIMIT) {
|
|
65
|
+
const exceeded = this.totalLength;
|
|
66
|
+
this.chunks = [];
|
|
67
|
+
this.totalLength = 0;
|
|
68
|
+
throw new TransportError(
|
|
69
|
+
TransportErrorCodes.MESSAGE_TOO_LARGE,
|
|
70
|
+
`Accumulated buffer (${exceeded} bytes) exceeds the allowed limit`,
|
|
71
|
+
{ accumulatedBytes: exceeded }
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
this.chunks.push(data);
|
|
75
|
+
let buffer = this.compact();
|
|
76
|
+
while (buffer.byteLength >= LENGTH_PREFIX_BYTES) {
|
|
77
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
78
|
+
const frameLength = view.getUint32(0, false);
|
|
79
|
+
if (frameLength > MAX_MESSAGE_SIZE_BYTES) {
|
|
80
|
+
this.chunks = [];
|
|
81
|
+
this.totalLength = 0;
|
|
82
|
+
throw new TransportError(
|
|
83
|
+
TransportErrorCodes.MESSAGE_TOO_LARGE,
|
|
84
|
+
`Incoming frame (${frameLength} bytes) exceeds the ${MAX_MESSAGE_SIZE_BYTES} byte limit`,
|
|
85
|
+
{ payloadSize: frameLength }
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
const totalNeeded = LENGTH_PREFIX_BYTES + frameLength;
|
|
89
|
+
if (buffer.byteLength < totalNeeded) {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
const frameBytes = buffer.subarray(LENGTH_PREFIX_BYTES, totalNeeded);
|
|
93
|
+
buffer = buffer.subarray(totalNeeded);
|
|
94
|
+
try {
|
|
95
|
+
const decoded = decode(frameBytes);
|
|
96
|
+
this.onFrame({
|
|
97
|
+
frameType: decoded.frameType,
|
|
98
|
+
requestId: decoded.requestId,
|
|
99
|
+
data: new Uint8Array(decoded.data)
|
|
100
|
+
});
|
|
101
|
+
} catch (err) {
|
|
102
|
+
this.chunks = [];
|
|
103
|
+
this.totalLength = 0;
|
|
104
|
+
throw new TransportError(
|
|
105
|
+
TransportErrorCodes.DECODE_FAILED,
|
|
106
|
+
`Failed to decode frame: ${err instanceof Error ? err.message : String(err)}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.chunks = buffer.byteLength > 0 ? [buffer] : [];
|
|
111
|
+
this.totalLength = buffer.byteLength;
|
|
112
|
+
}
|
|
113
|
+
reset() {
|
|
114
|
+
this.chunks = [];
|
|
115
|
+
this.totalLength = 0;
|
|
116
|
+
}
|
|
117
|
+
compact() {
|
|
118
|
+
if (this.chunks.length === 0) {
|
|
119
|
+
return new Uint8Array(0);
|
|
120
|
+
}
|
|
121
|
+
if (this.chunks.length === 1) {
|
|
122
|
+
return this.chunks[0];
|
|
123
|
+
}
|
|
124
|
+
const combined = new Uint8Array(this.totalLength);
|
|
125
|
+
let offset = 0;
|
|
126
|
+
for (const chunk of this.chunks) {
|
|
127
|
+
combined.set(chunk, offset);
|
|
128
|
+
offset += chunk.byteLength;
|
|
129
|
+
}
|
|
130
|
+
this.chunks = [combined];
|
|
131
|
+
return combined;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export { DEFAULT_TCP_CONFIG, FRAME_TYPE_REQUEST, FRAME_TYPE_RESPONSE, FRAME_TYPE_STREAM_CHUNK, FRAME_TYPE_STREAM_END, FrameParser, decodeTransportMessage, encodeFrame, encodeTransportMessage };
|