@lde/search-typesense 0.38.5 → 0.39.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/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { BlueGreenRebuild } from './blue-green-rebuild.js';
2
2
  export type { BlueGreenRebuildOptions } from './blue-green-rebuild.js';
3
3
  export { InPlaceRebuild } from './in-place-rebuild.js';
4
4
  export type { InPlaceRebuildOptions } from './in-place-rebuild.js';
5
- export { RebuildAlreadyRunning } from './lock.js';
5
+ export { TypesenseRebuildRequests } from './rebuild-requests.js';
6
6
  export { buildCollectionDefinition } from './collection-definition.js';
7
7
  export type { CollectionDefinitionOptions } from './collection-definition.js';
8
8
  export { deriveCollectionName } from './collection-name.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,YAAY,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC/E,YAAY,EACV,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,YAAY,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC/E,YAAY,EACV,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { BlueGreenRebuild } from './blue-green-rebuild.js';
2
2
  export { InPlaceRebuild } from './in-place-rebuild.js';
3
- export { RebuildAlreadyRunning } from './lock.js';
3
+ export { TypesenseRebuildRequests } from './rebuild-requests.js';
4
4
  export { buildCollectionDefinition } from './collection-definition.js';
5
5
  export { deriveCollectionName } from './collection-name.js';
6
6
  export { buildSearchParams } from './query-compiler.js';
package/dist/lock.d.ts CHANGED
@@ -1,14 +1,6 @@
1
1
  import type { Client, CollectionCreateSchema } from 'typesense';
2
2
  /** A held lock older than this (ms) is reclaimed. */
3
3
  export declare const DEFAULT_LOCK_TTL_MS: number;
4
- /**
5
- * Another run already holds the index’s rebuild lock, so this run refuses to
6
- * open. Rebuilds are single-flight per index across pods; catch this to treat
7
- * a concurrent rebuild as a graceful skip rather than a failure.
8
- */
9
- export declare class RebuildAlreadyRunning extends Error {
10
- constructor(name: string);
11
- }
12
4
  /**
13
5
  * Open a run under the index’s single-flight lock: acquire it (throwing
14
6
  * {@link RebuildAlreadyRunning} when another rebuild holds it), run the
@@ -1 +1 @@
1
- {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAIhE,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,QAAiB,CAAC;AAElD;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,IAAI,EAAE,MAAM;CAIzB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,GAAG,EACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACxB,OAAO,CAAC,GAAG,CAAC,CAUd;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED,yEAAyE;AACzE,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7E;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,sBAAsB,GACnC,OAAO,CAAC,OAAO,CAAC,CAmBlB;AA+BD,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE7D"}
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAKhE,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,QAAiB,CAAC;AAElD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,GAAG,EACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACxB,OAAO,CAAC,GAAG,CAAC,CAUd;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED,yEAAyE;AACzE,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7E;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,sBAAsB,GACnC,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAgCD,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE7D"}
package/dist/lock.js CHANGED
@@ -1,17 +1,7 @@
1
+ import { RebuildAlreadyRunning } from '@lde/search';
1
2
  const LOCK_COLLECTION = 'rebuild_locks';
2
3
  /** A held lock older than this (ms) is reclaimed. */
3
4
  export const DEFAULT_LOCK_TTL_MS = 10 * 60 * 1000;
4
- /**
5
- * Another run already holds the index’s rebuild lock, so this run refuses to
6
- * open. Rebuilds are single-flight per index across pods; catch this to treat
7
- * a concurrent rebuild as a graceful skip rather than a failure.
8
- */
9
- export class RebuildAlreadyRunning extends Error {
10
- constructor(name) {
11
- super(`Another rebuild of “${name}” is already running`);
12
- this.name = 'RebuildAlreadyRunning';
13
- }
14
- }
15
5
  /**
16
6
  * Open a run under the index’s single-flight lock: acquire it (throwing
17
7
  * {@link RebuildAlreadyRunning} when another rebuild holds it), run the
@@ -111,7 +101,8 @@ export async function ensureCollectionExists(client, name, schema) {
111
101
  return false;
112
102
  }
113
103
  }
114
- /** Take over the lock if its holder has not refreshed it within `ttlMs`. */
104
+ /** Take over the lock if it was acquired more than `ttlMs` ago. Nothing
105
+ * refreshes a held lock, so a run outliving the TTL can lose it. */
115
106
  async function reclaimIfStale(client, name, ttlMs) {
116
107
  let held;
117
108
  try {
@@ -0,0 +1,25 @@
1
+ import type { Client } from 'typesense';
2
+ import type { RebuildRequests } from '@lde/search/adapter';
3
+ /**
4
+ * An index’s rebuild requests ({@link RebuildRequests}) in Typesense, for
5
+ * `requestRebuild` from `@lde/search`: one document per index in a `rebuild_requests`
6
+ * collection, created on demand, holding a random id that each request
7
+ * replaces.
8
+ *
9
+ * Pass the same `name` the index’s rebuild writer locks on – its
10
+ * `collectionName`. The requests live apart from the `rebuild_locks`
11
+ * collection because releasing a lock deletes its document, and a request has
12
+ * to outlive the release: the run holding the lock reads it afterwards.
13
+ */
14
+ export declare class TypesenseRebuildRequests implements RebuildRequests {
15
+ private readonly client;
16
+ private readonly name;
17
+ constructor(client: Client, name: string);
18
+ /** Record a new request for the index, creating the `rebuild_requests`
19
+ * collection on the first request ever. */
20
+ record(): Promise<void>;
21
+ /** The index’s latest request id, or `undefined` when none was recorded. */
22
+ latest(): Promise<string | undefined>;
23
+ private documents;
24
+ }
25
+ //# sourceMappingURL=rebuild-requests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rebuild-requests.d.ts","sourceRoot":"","sources":["../src/rebuild-requests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAK3D;;;;;;;;;;GAUG;AACH,qBAAa,wBAAyB,YAAW,eAAe;IAE5D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM;IAG/B;gDAC4C;IACtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B,4EAA4E;IACtE,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAgB3C,OAAO,CAAC,SAAS;CAGlB"}
@@ -0,0 +1,60 @@
1
+ import { ensureCollectionExists, httpStatus } from './lock.js';
2
+ const REQUEST_COLLECTION = 'rebuild_requests';
3
+ /**
4
+ * An index’s rebuild requests ({@link RebuildRequests}) in Typesense, for
5
+ * `requestRebuild` from `@lde/search`: one document per index in a `rebuild_requests`
6
+ * collection, created on demand, holding a random id that each request
7
+ * replaces.
8
+ *
9
+ * Pass the same `name` the index’s rebuild writer locks on – its
10
+ * `collectionName`. The requests live apart from the `rebuild_locks`
11
+ * collection because releasing a lock deletes its document, and a request has
12
+ * to outlive the release: the run holding the lock reads it afterwards.
13
+ */
14
+ export class TypesenseRebuildRequests {
15
+ client;
16
+ name;
17
+ constructor(client, name) {
18
+ this.client = client;
19
+ this.name = name;
20
+ }
21
+ /** Record a new request for the index, creating the `rebuild_requests`
22
+ * collection on the first request ever. */
23
+ async record() {
24
+ const request = { id: this.name, request: crypto.randomUUID() };
25
+ try {
26
+ await this.documents().upsert(request);
27
+ }
28
+ catch (error) {
29
+ if (httpStatus(error) !== 404) {
30
+ throw error;
31
+ }
32
+ // First request ever: the collection does not exist yet.
33
+ await ensureCollectionExists(this.client, REQUEST_COLLECTION, () => ({
34
+ name: REQUEST_COLLECTION,
35
+ fields: [{ name: 'request', type: 'string' }],
36
+ }));
37
+ await this.documents().upsert(request);
38
+ }
39
+ }
40
+ /** The index’s latest request id, or `undefined` when none was recorded. */
41
+ async latest() {
42
+ try {
43
+ const { request } = (await this.client
44
+ .collections(REQUEST_COLLECTION)
45
+ .documents(this.name)
46
+ .retrieve());
47
+ return request;
48
+ }
49
+ catch (error) {
50
+ // No request recorded for this index, or none for any index yet.
51
+ if (httpStatus(error) === 404) {
52
+ return undefined;
53
+ }
54
+ throw error;
55
+ }
56
+ }
57
+ documents() {
58
+ return this.client.collections(REQUEST_COLLECTION).documents();
59
+ }
60
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/search-typesense",
3
- "version": "0.38.5",
3
+ "version": "0.39.0",
4
4
  "description": "Typesense implementation of the @lde/search SearchEngine port: collection-schema builder, query compiler, label-resolving result reconstruction, and blue/green index lifecycle. Engine-specific (Typesense) but domain-agnostic.",
5
5
  "repository": {
6
6
  "url": "git+https://github.com/ldelements/lde.git",
@@ -25,7 +25,7 @@
25
25
  "!**/*.tsbuildinfo"
26
26
  ],
27
27
  "dependencies": {
28
- "@lde/search": "^0.32.3",
28
+ "@lde/search": "^0.33.0",
29
29
  "@lde/text-normalization": "^0.2.0",
30
30
  "tslib": "^2.3.0",
31
31
  "typesense": "^3.1.1"