ydb-qdrant 4.3.6 → 4.5.0

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 CHANGED
@@ -4,9 +4,15 @@
4
4
  [![Tests](https://img.shields.io/github/actions/workflow/status/astandrik/ydb-qdrant/ci-tests.yml?branch=main&label=tests)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-tests.yml)
5
5
  [![Integration Tests](https://img.shields.io/github/actions/workflow/status/astandrik/ydb-qdrant/ci-integration.yml?branch=main&label=integration%20tests)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-integration.yml)
6
6
  [![Coverage](https://coveralls.io/repos/github/astandrik/ydb-qdrant/badge.svg?branch=main)](https://coveralls.io/github/astandrik/ydb-qdrant?branch=main)
7
+
8
+ [![Recall (multi_table)](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astandrik/ydb-qdrant/recall-badges/recall-multi-table.json)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-recall.yml)
9
+ [![Recall (one_table)](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astandrik/ydb-qdrant/recall-badges/recall-one-table.json)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-recall.yml)
10
+ [![F1 (multi_table)](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astandrik/ydb-qdrant/recall-badges/f1-multi-table.json)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-recall.yml)
11
+ [![F1 (one_table)](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astandrik/ydb-qdrant/recall-badges/f1-one-table.json)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-recall.yml)
12
+
7
13
  [![npm version](https://img.shields.io/npm/v/ydb-qdrant.svg)](https://www.npmjs.com/package/ydb-qdrant)
8
14
  [![Docker Image](https://img.shields.io/badge/docker-ghcr.io%2Fastandrik%2Fydb--qdrant-blue?logo=docker)](https://github.com/users/astandrik/packages/container/package/ydb-qdrant)
9
- [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
15
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
10
16
 
11
17
  # YDB Qdrant-compatible Service
12
18
 
@@ -23,6 +29,13 @@ Architecture diagrams: [docs page](http://ydb-qdrant.tech/docs/)
23
29
 
24
30
  ![Architecture diagram](https://ydb-qdrant.tech/assets/diagram.svg)
25
31
 
32
+ ## Documentation
33
+
34
+ - **Vector dimensions and embedding models**: [docs/vector-dimensions.md](docs/vector-dimensions.md)
35
+ - **Deployment and Docker options**: [docs/deployment-and-docker.md](docs/deployment-and-docker.md)
36
+ - **Architecture, storage layout, and vector indexing**: [docs/architecture-and-storage.md](docs/architecture-and-storage.md)
37
+ - **Evaluation, CI, and release process**: [docs/evaluation-and-ci.md](docs/evaluation-and-ci.md)
38
+
26
39
  ## Requirements
27
40
  - Node.js 18+
28
41
  - A YDB endpoint and database path
@@ -171,50 +184,7 @@ This pattern avoids running a separate HTTP service: vector search is executed d
171
184
 
172
185
  ## Recommended Vector Dimensions
173
186
 
174
- When creating a collection, you must specify the vector `size` matching your embedding model. Below are popular models with their dimensions and typical use cases:
175
-
176
- ### Commercial API Models
177
-
178
- | Provider | Model | Dimensions | Use Cases |
179
- |----------|-------|------------|-----------|
180
- | **OpenAI** | `text-embedding-3-small` | 1536 (default, can reduce to 256-1536) | RAG, semantic search, general-purpose embeddings |
181
- | **OpenAI** | `text-embedding-3-large` | 3072 (default, can reduce to 256, 512, 1024, 1536, 3072) | High-accuracy RAG, multilingual tasks |
182
- | **OpenAI** | `text-embedding-ada-002` | 1536 | Legacy model, widely adopted |
183
- | **OpenAI** (Legacy) | `text-search-curie-doc-001` | 4096 | Legacy GPT-3 model, deprecated |
184
- | **OpenAI** (Legacy) | `text-search-davinci-doc-001` | 12288 | Legacy GPT-3 model, deprecated |
185
- | **Cohere** | `embed-v4.0` | 256, 512, 1024, 1536 (default) | Multimodal (text + image), RAG, enterprise search |
186
- | **Cohere** | `embed-english-v3.0` | 1024 | English text, semantic search, classification |
187
- | **Cohere** | `embed-multilingual-v3.0` | 1024 | 100+ languages, long-document retrieval, clustering |
188
- | **Google** | `gemini-embedding-001` | 3072 (configurable) | Multilingual, general-purpose, RAG |
189
- | **Google** | `text-embedding-004` | 768 | General-purpose text embeddings |
190
- | **Google** | `text-embedding-005` | 768 | Improved version of text-embedding-004 |
191
- | **Google** | `text-multilingual-embedding-002` | 768 | Multilingual text embeddings |
192
-
193
- ### Open-Source Models (HuggingFace)
194
-
195
- | Model | Dimensions | Use Cases |
196
- |-------|------------|-----------|
197
- | `sentence-transformers/all-MiniLM-L6-v2` | 384 | Fast semantic search, low-resource environments |
198
- | `BAAI/bge-base-en-v1.5` | 768 | RAG, retrieval, English text |
199
- | `BAAI/bge-large-en-v1.5` | 1024 | High-accuracy RAG, English text |
200
- | `BAAI/bge-m3` | 1024 | Multilingual, dense/sparse/multi-vector |
201
- | `intfloat/e5-base-v2` | 768 | General retrieval, English text |
202
- | `intfloat/e5-large-v2` | 1024 | High-accuracy retrieval, English text |
203
- | `intfloat/e5-mistral-7b-instruct` | 4096 | High-dimensional embeddings, advanced RAG |
204
- | `nomic-ai/nomic-embed-text-v1` | 768 | General-purpose, open weights |
205
-
206
- ### Choosing Dimensions
207
-
208
- - **Higher dimensions (1024-4096)**: Better semantic fidelity, higher storage/compute costs
209
- - **Lower dimensions (384-768)**: Faster queries, lower costs, suitable for many use cases
210
- - **Variable dimensions**: Some models (OpenAI v3, Cohere v4) allow dimension reduction with minimal accuracy loss
211
- - **Legacy models**: Older OpenAI GPT-3 models (Curie: 4096, Davinci: 12288) are deprecated but may still be in use
212
-
213
- **References:**
214
- - [OpenAI Embeddings Guide](https://platform.openai.com/docs/guides/embeddings)
215
- - [Cohere Embed Models](https://docs.cohere.com/docs/cohere-embed)
216
- - [Google Gemini Embeddings](https://ai.google.dev/gemini-api/docs/embeddings)
217
- - [HuggingFace Sentence Transformers](https://huggingface.co/sentence-transformers)
187
+ For full tables of popular embedding models and their dimensions, see [docs/vector-dimensions.md](docs/vector-dimensions.md).
218
188
 
219
189
  ## Quick Start
220
190
 
@@ -231,6 +201,23 @@ When creating a collection, you must specify the vector `size` matching your emb
231
201
  - API key optional (not enforced)
232
202
  - Full control and privacy
233
203
 
204
+ **Option 3: All-in-one local YDB + ydb-qdrant (Docker)**
205
+
206
+ Run a single container that includes both YDB and ydb-qdrant (no external YDB required):
207
+
208
+ ```bash
209
+ docker run -d --name ydb-qdrant-local \
210
+ -p 8080:8080 \
211
+ -p 8765:8765 \
212
+ ghcr.io/astandrik/ydb-qdrant-local:latest
213
+ ```
214
+
215
+ - HTTP API available at `http://localhost:8080`
216
+ - YDB Embedded UI at `http://localhost:8765`
217
+ - No credentials or env vars needed for local dev
218
+
219
+ For detailed configuration and env tuning, see [docs/deployment-and-docker.md](docs/deployment-and-docker.md).
220
+
234
221
  ### cURL smoke test (Self-hosted)
235
222
  ```bash
236
223
  # 1) Install & run
@@ -281,11 +268,9 @@ curl -s http://localhost:8080/health
281
268
 
282
269
  Published container: [`ghcr.io/astandrik/ydb-qdrant`](https://github.com/users/astandrik/packages/container/package/ydb-qdrant)
283
270
 
284
- **Option A – pull the published image (recommended)**
271
+ Basic example:
285
272
 
286
273
  ```bash
287
- docker pull ghcr.io/astandrik/ydb-qdrant:latest
288
-
289
274
  docker run -d --name ydb-qdrant \
290
275
  -p 8080:8080 \
291
276
  -e YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135 \
@@ -295,115 +280,7 @@ docker run -d --name ydb-qdrant \
295
280
  ghcr.io/astandrik/ydb-qdrant:latest
296
281
  ```
297
282
 
298
- **Option B build the image locally**
299
-
300
- From the `ydb-qdrant/` directory:
301
-
302
- ```bash
303
- docker build -t ydb-qdrant:latest .
304
-
305
- docker run -d --name ydb-qdrant \
306
- -p 8080:8080 \
307
- -e YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135 \
308
- -e YDB_DATABASE=/ru-central1/<cloud>/<db> \
309
- -e YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS=/sa-key.json \
310
- -v /abs/path/sa-key.json:/sa-key.json:ro \
311
- ydb-qdrant:latest
312
- ```
313
-
314
- #### Docker (all-in-one: local YDB + ydb-qdrant)
315
-
316
- For a single-container local dev/demo setup with both YDB and ydb-qdrant inside:
317
-
318
- ```bash
319
- docker pull ghcr.io/astandrik/ydb-qdrant-local:latest
320
-
321
- docker run -d --name ydb-qdrant-local \
322
- -p 8080:8080 \
323
- -p 8765:8765 \
324
- ghcr.io/astandrik/ydb-qdrant-local:latest
325
- ```
326
-
327
- Key env vars (all optional; the image provides sensible defaults, override only when you need custom tuning):
328
-
329
- - YDB / local YDB:
330
- - `YDB_LOCAL_GRPC_PORT` (default `2136`): internal YDB gRPC port.
331
- - `YDB_LOCAL_MON_PORT` (default `8765`): internal YDB Embedded UI HTTP port.
332
- - `YDB_DATABASE` (default `/local`).
333
- - `YDB_ANONYMOUS_CREDENTIALS` (default `1` inside this image).
334
- - `YDB_USE_IN_MEMORY_PDISKS` (default `0`, values `0`/`1`): store data in RAM only when `1` (fast, non-persistent).
335
- - `YDB_LOCAL_SURVIVE_RESTART` (default `0`, values `0`/`1`): control persistence across restarts when using a mounted data volume.
336
- - `YDB_DEFAULT_LOG_LEVEL`, `YDB_FEATURE_FLAGS`, `YDB_ENABLE_COLUMN_TABLES`, `YDB_KAFKA_PROXY_PORT`, `POSTGRES_USER`, `POSTGRES_PASSWORD` – passed through to YDB as in the official `local-ydb` image.
337
-
338
- - ydb-qdrant:
339
- - `PORT` (default `8080`): HTTP port inside the container.
340
- - `LOG_LEVEL` (default `info`).
341
- - `VECTOR_INDEX_BUILD_ENABLED` (default `true` in `multi_table` mode, `false` in `one_table` mode).
342
- - `YDB_QDRANT_COLLECTION_STORAGE_MODE` / `YDB_QDRANT_TABLE_LAYOUT` (`multi_table` or `one_table`).
343
- - `YDB_QDRANT_GLOBAL_POINTS_AUTOMIGRATE`.
344
-
345
- > Note: In the `ydb-qdrant-local` image, `YDB_ENDPOINT` is unconditionally set to `grpc://localhost:<YDB_LOCAL_GRPC_PORT>` by the entrypoint — any user-provided value is ignored. Use the standalone `ydb-qdrant` image if you need to connect to an external YDB.
346
-
347
- #### Apple Silicon (Mac) notes
348
-
349
- The `ydb-qdrant-local` image is built on top of the `local-ydb` Docker image, which is x86_64/amd64-only. On Apple Silicon (M1/M2/M3) you need to run it under x86_64/amd64 emulation:
350
-
351
- - Enable Rosetta (x86_64/amd64 emulation) in your Docker backend:
352
- - Docker Desktop: enable Rosetta to run x86_64/amd64 containers.
353
- - Or use Colima as in the YDB docs:
354
- - `colima start --arch aarch64 --vm-type=vz --vz-rosetta`
355
- - When running the container, force the amd64 platform explicitly:
356
-
357
- ```bash
358
- docker run --platform linux/amd64 -d --name ydb-qdrant-local \
359
- -p 8080:8080 -p 8765:8765 \
360
- ghcr.io/astandrik/ydb-qdrant-local:latest
361
- ```
362
-
363
- This keeps behavior aligned with the official YDB `local-ydb` image recommendations for macOS/Apple Silicon.
364
-
365
- #### Docker Compose
366
-
367
- Example `docker-compose.yml` (can be used instead of raw `docker run`):
368
-
369
- ```yaml
370
- services:
371
- ydb-qdrant:
372
- image: ghcr.io/astandrik/ydb-qdrant:latest
373
- ports:
374
- - "8080:8080"
375
- env_file:
376
- - .env
377
- environment:
378
- YDB_ENDPOINT: ${YDB_ENDPOINT}
379
- YDB_DATABASE: ${YDB_DATABASE}
380
- YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS: /sa-key.json
381
- PORT: ${PORT:-8080}
382
- LOG_LEVEL: ${LOG_LEVEL:-info}
383
- volumes:
384
- - ${YDB_SA_KEY_PATH}:/sa-key.json:ro
385
- ```
386
-
387
- Example `.env` (per environment):
388
-
389
- ```bash
390
- YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135
391
- YDB_DATABASE=/ru-central1/<cloud>/<db>
392
- YDB_SA_KEY_PATH=/abs/path/to/ydb-sa.json
393
- PORT=8080
394
- LOG_LEVEL=info
395
- ```
396
-
397
- - **Updating to a newer image with Compose** (no rebuild):
398
- - Pull the latest tag and restart the service:
399
- ```bash
400
- docker-compose pull ydb-qdrant
401
- docker-compose up -d ydb-qdrant
402
- ```
403
-
404
- - **Environment**: uses the same variables as documented in **Configure credentials** (`YDB_ENDPOINT`, `YDB_DATABASE`, one of the `YDB_*_CREDENTIALS` options, optional `PORT`/`LOG_LEVEL`).
405
- - **Qdrant URL for tools/clients**: set to `http://localhost:8080` (or `http://<host>:<hostPort>` if you map a different port).
406
- - **Health check inside container**: `GET http://localhost:8080/health`.
283
+ For full deployment options (local builds, all-in-one image, Docker Compose, Apple Silicon notes), see [docs/deployment-and-docker.md](docs/deployment-and-docker.md) — including an optional “Persistence across restarts” example for the `ydb-qdrant-local` image when you want embedded YDB data to survive container restarts.
407
284
 
408
285
 
409
286
  ## API Reference
@@ -450,63 +327,10 @@ curl -X POST http://localhost:8080/collections/mycol/points/delete \
450
327
  -d '{"points": ["1"]}'
451
328
  ```
452
329
 
453
- ## Notes
454
- - Storage layout:
455
- - **multi_table** (default): one YDB table per collection; metadata is tracked in `qdr__collections`.
456
- - **one_table**: a single global table `qdrant_all_points` with `(uid, point_id)` PK, where `uid` encodes tenant+collection. Columns: `uid Utf8`, `point_id Utf8`, `embedding String` (binary float), `embedding_bit String` (bit‑quantized), `payload JsonDocument`.
457
- - **Schema migrations** (one_table mode): automatic schema/backfill steps for `qdrant_all_points` are disabled by default. To opt in, set `YDB_QDRANT_GLOBAL_POINTS_AUTOMIGRATE=true` after backing up data; otherwise the service will error if the `embedding_bit` column is missing or needs backfill.
458
- - Per‑collection table schema (multi_table): `point_id Utf8` (PK), `embedding String` (binary), `payload JsonDocument`.
459
- - Vectors are serialized with `Knn::ToBinaryStringFloat`.
460
- - Search uses a single-phase top‑k over `embedding` with automatic YDB vector index (`emb_idx`) when available; falls back to table scan if missing.
461
- - **Vector index auto-build** (multi_table mode only): After ≥100 points upserted + 5s quiet window, a `vector_kmeans_tree` index (levels=1, clusters=128) is built automatically. Incremental updates (<100 points) skip index rebuild. In one_table mode, vector indexes are not supported; searches use a two‑phase approximate+exact flow over `qdrant_all_points` (bit‑quantized candidates via `embedding_bit` using the corresponding distance function, then exact re‑ranking over `embedding`). Note: For Dot metric, Phase 1 uses CosineDistance as a proxy since there is no direct distance equivalent for inner product on bit vectors.
462
- - **Concurrency**: During index rebuilds, YDB may return transient `Aborted`/schema metadata errors. Upserts include bounded retries with backoff to handle this automatically.
463
- - Filters are not yet modeled; can be added if needed.
464
-
465
- ## Scoring semantics
466
- - Cosine/Dot: higher score is better; `score_threshold` filters with `>=`.
467
- - Euclid/Manhattan: lower score is better; `score_threshold` filters with `<=`.
468
-
469
- ## Request normalization (Qdrant-compatible)
470
- - Accepts `limit` as alias of `top`.
471
- - Accepts `with_payload` as boolean/object/array (object/array treated as `true`).
472
- - Extracts query vector from common shapes: `vector`, `embedding`, `query.vector`, `query.nearest.vector`, or nested keys.
473
-
474
- ## Qdrant compatibility scope
475
- This service implements a minimal subset expected by common tooling:
476
- - Create/get/delete collection
477
- - Upsert points
478
- - Top‑k search with optional payload
479
- - Delete points
480
-
481
- Compatibility notes:
482
- - Accepts `PUT /collections/:collection/points` as an alias of upsert.
483
- - Accepts `POST /collections/:collection/points/query` as an alias of search.
484
- - Accepts `limit` as an alias of `top`; honors `score_threshold`.
485
- - Search response shape: `{ status: "ok", result: { points: [{ id, score, payload? }] } }`.
486
- - `PUT /collections/:collection/index` is a no-op (Qdrant compatibility; Roo Code calls this for payload indexes). The YDB vector index (`emb_idx`) is built automatically after ≥100 points are upserted + 5-second quiet window. Incremental updates (<100 points) skip rebuild.
487
-
488
- For broader Qdrant API coverage, extend routes in `src/routes/*`.
489
-
490
- ## Releasing & publishing (maintainers)
491
-
492
- - **Versioning**
493
- - Use semantic versioning as described in the npm docs.
494
- - From `ydb-qdrant/`, run `npm version patch|minor|major` to bump the version and create a git tag (for example, `ydb-qdrant-v0.2.0`).
495
- - **Manual publish**
496
- - Ensure you are logged in to npm (`npm whoami`).
497
- - From `ydb-qdrant/`, run:
498
- - `npm publish`
499
- This will run tests and build via the `prepublishOnly` script before uploading the tarball.
500
- - **CI publish**
501
- - GitHub Actions workflow `.github/workflows/publish-ydb-qdrant.yml` publishes on tags matching `ydb-qdrant-v*`.
502
- - Configure the `NPM_TOKEN` secret in the repository; the workflow runs `npm ci`, `npm test`, `npm run build`, and `npm publish`.
503
-
504
- ## References
505
- - YDB docs (overview): https://ydb.tech/docs/en/
506
- - YDB vector indexes (vector_kmeans_tree): https://ydb.tech/docs/en/dev/vector-indexes
507
- - YDB VIEW syntax for indexes: https://ydb.tech/docs/en/yql/reference/syntax/select/secondary_index
508
- - YQL getting started: https://ydb.tech/docs/en/getting_started/yql/
509
- - YQL reference (syntax, functions): https://ydb.tech/docs/en/yql/reference/
510
- - YQL functions index: https://ydb.tech/docs/en/yql/reference/functions/
511
- - ydb-sdk (Node.js): https://github.com/ydb-platform/ydb-nodejs-sdk
512
- - YDB Cloud (endpoints, auth): https://cloud.yandex.com/en/docs/ydb/
330
+ ## Architecture and Storage
331
+
332
+ For details on the YDB storage layout (multi_table vs one_table), vector serialization, vector index auto-build behavior, request normalization, and Qdrant compatibility semantics, see [docs/architecture-and-storage.md](docs/architecture-and-storage.md).
333
+
334
+ ## Evaluation, CI, and Release
335
+
336
+ Badges at the top of this README link to build, test, integration, and recall/F1 workflows. For a deeper explanation of how recall is measured and how publishing to npm works, see [docs/evaluation-and-ci.md](docs/evaluation-and-ci.md).
package/dist/server.d.ts CHANGED
@@ -1 +1,3 @@
1
+ import type { Request, Response } from "express";
2
+ export declare function healthHandler(_req: Request, res: Response): Promise<void>;
1
3
  export declare function buildServer(): import("express-serve-static-core").Express;
package/dist/server.js CHANGED
@@ -2,11 +2,20 @@ import express from "express";
2
2
  import { collectionsRouter } from "./routes/collections.js";
3
3
  import { pointsRouter } from "./routes/points.js";
4
4
  import { requestLogger } from "./middleware/requestLogger.js";
5
+ import { isYdbAvailable } from "./ydb/client.js";
6
+ export async function healthHandler(_req, res) {
7
+ const ok = await isYdbAvailable();
8
+ if (!ok) {
9
+ res.status(503).json({ status: "error", error: "YDB unavailable" });
10
+ return;
11
+ }
12
+ res.json({ status: "ok" });
13
+ }
5
14
  export function buildServer() {
6
15
  const app = express();
7
16
  app.use(express.json({ limit: "20mb" }));
8
17
  app.use(requestLogger);
9
- app.get("/health", (_req, res) => res.json({ status: "ok" }));
18
+ app.get("/health", healthHandler);
10
19
  app.use("/collections", collectionsRouter);
11
20
  app.use("/collections", pointsRouter);
12
21
  return app;
@@ -7,6 +7,8 @@ type DriverConfig = {
7
7
  connectionString?: string;
8
8
  authService?: IAuthService;
9
9
  };
10
+ export declare function __setDriverForTests(fake: unknown): void;
10
11
  export declare function configureDriver(config: DriverConfig): void;
11
12
  export declare function readyOrThrow(): Promise<void>;
12
13
  export declare function withSession<T>(fn: (s: Session) => Promise<T>): Promise<T>;
14
+ export declare function isYdbAvailable(timeoutMs?: number): Promise<boolean>;
@@ -3,8 +3,14 @@ import { YDB_DATABASE, YDB_ENDPOINT } from "../config/env.js";
3
3
  const require = createRequire(import.meta.url);
4
4
  const { Driver, getCredentialsFromEnv, Types, TypedValues, TableDescription, Column, } = require("ydb-sdk");
5
5
  export { Types, TypedValues, TableDescription, Column };
6
+ const DRIVER_READY_TIMEOUT_MS = 15000;
7
+ const TABLE_SESSION_TIMEOUT_MS = 20000;
8
+ const YDB_HEALTHCHECK_READY_TIMEOUT_MS = 5000;
6
9
  let overrideConfig;
7
10
  let driver;
11
+ export function __setDriverForTests(fake) {
12
+ driver = fake;
13
+ }
8
14
  export function configureDriver(config) {
9
15
  if (driver) {
10
16
  // Driver already created; keep existing connection settings.
@@ -30,12 +36,21 @@ function getOrCreateDriver() {
30
36
  }
31
37
  export async function readyOrThrow() {
32
38
  const d = getOrCreateDriver();
33
- const ok = await d.ready(10000);
39
+ const ok = await d.ready(DRIVER_READY_TIMEOUT_MS);
34
40
  if (!ok) {
35
- throw new Error("YDB driver is not ready in 10s. Check connectivity and credentials.");
41
+ throw new Error(`YDB driver is not ready in ${DRIVER_READY_TIMEOUT_MS / 1000}s. Check connectivity and credentials.`);
36
42
  }
37
43
  }
38
44
  export async function withSession(fn) {
39
45
  const d = getOrCreateDriver();
40
- return await d.tableClient.withSession(fn, 15000);
46
+ return await d.tableClient.withSession(fn, TABLE_SESSION_TIMEOUT_MS);
47
+ }
48
+ export async function isYdbAvailable(timeoutMs = YDB_HEALTHCHECK_READY_TIMEOUT_MS) {
49
+ const d = getOrCreateDriver();
50
+ try {
51
+ return await d.ready(timeoutMs);
52
+ }
53
+ catch {
54
+ return false;
55
+ }
41
56
  }
@@ -60,7 +60,11 @@ export async function ensureGlobalPointsTable() {
60
60
  ALTER TABLE ${GLOBAL_POINTS_TABLE}
61
61
  ADD COLUMN embedding_bit String;
62
62
  `;
63
- await s.executeQuery(alterDdl);
63
+ const rawSession = s;
64
+ await rawSession.api.executeSchemeQuery({
65
+ sessionId: rawSession.sessionId,
66
+ yqlText: alterDdl,
67
+ });
64
68
  logger.info(`added embedding_bit column to existing table ${GLOBAL_POINTS_TABLE}`);
65
69
  needsBackfill = true;
66
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-qdrant",
3
- "version": "4.3.6",
3
+ "version": "4.5.0",
4
4
  "main": "dist/package/api.js",
5
5
  "types": "dist/package/api.d.ts",
6
6
  "exports": {
@@ -16,7 +16,8 @@
16
16
  "scripts": {
17
17
  "test": "vitest run --exclude \"test/integration/**\"",
18
18
  "test:coverage": "vitest run --coverage --exclude \"test/integration/**\"",
19
- "test:integration": "VECTOR_INDEX_BUILD_ENABLED=false vitest run test/integration/YdbRealIntegration.index-disabled.test.ts && VECTOR_INDEX_BUILD_ENABLED=true vitest run test/integration/YdbRealIntegration.test.ts",
19
+ "test:integration": "VECTOR_INDEX_BUILD_ENABLED=false vitest run test/integration/YdbRealIntegration.index-disabled.test.ts && VECTOR_INDEX_BUILD_ENABLED=true vitest run test/integration/YdbRealIntegration.test.ts test/integration/YdbRecallIntegration.test.ts && YDB_QDRANT_COLLECTION_STORAGE_MODE=one_table vitest run test/integration/YdbRealIntegration.one-table.test.ts",
20
+ "test:recall": "VECTOR_INDEX_BUILD_ENABLED=true vitest run test/integration/YdbRecallIntegration.test.ts && YDB_QDRANT_COLLECTION_STORAGE_MODE=one_table vitest run test/integration/YdbRealIntegration.one-table.test.ts",
20
21
  "build": "tsc -p tsconfig.json",
21
22
  "typecheck": "tsc -p tsconfig.json --noEmit",
22
23
  "dev": "tsx watch src/index.ts",
@@ -45,7 +46,7 @@
45
46
  "zod"
46
47
  ],
47
48
  "author": "",
48
- "license": "ISC",
49
+ "license": "Apache-2.0",
49
50
  "description": "Qdrant-compatible Node.js/TypeScript API that stores/searches embeddings in YDB using single-phase top-k vector search with an automatic vector index and table-scan fallback.",
50
51
  "type": "module",
51
52
  "publishConfig": {
@@ -80,4 +81,4 @@
80
81
  "typescript-eslint": "^8.47.0",
81
82
  "vitest": "^4.0.12"
82
83
  }
83
- }
84
+ }