@danielsimonjr/memoryjs 2.7.0 → 2.8.1

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.cts CHANGED
@@ -8480,10 +8480,13 @@ interface TaskSubmitOptions {
8480
8480
  }
8481
8481
  /**
8482
8482
  * Handle returned by `submitWithHandle`. The `result` promise settles when
8483
- * the task finishes; `cancel()` evicts a still-pending task from the queue
8484
- * (returns `true`) or signals a request-cancellation flag on a running task
8485
- * (returns `false` `workerpool` itself doesn't support hard-cancel and
8486
- * terminating mid-task is destructive).
8483
+ * the task finishes; `cancel()` performs two-tier cancellation:
8484
+ *
8485
+ * - If still pending in the queue: evict cleanly. Returns `true`.
8486
+ * - If already dispatched: propagate to the underlying
8487
+ * `WorkerpoolPromise.cancel()` so the running worker rejects with
8488
+ * `CancellationError`. Returns `true` if the workerpool promise was
8489
+ * still pending at the moment of cancel; `false` if it already settled.
8487
8490
  */
8488
8491
  interface TaskHandle<R> {
8489
8492
  id: string;
@@ -8534,6 +8537,7 @@ declare class WorkerTaskManager {
8534
8537
  private readonly touchedPoolIds;
8535
8538
  private readonly cancelledTaskIds;
8536
8539
  private readonly handleStatus;
8540
+ private readonly liveExecPromises;
8537
8541
  constructor(opts?: {
8538
8542
  /** Max concurrent tasks across the queue. Default: cpus − 1. */
8539
8543
  concurrency?: number;
package/dist/index.d.ts CHANGED
@@ -8480,10 +8480,13 @@ interface TaskSubmitOptions {
8480
8480
  }
8481
8481
  /**
8482
8482
  * Handle returned by `submitWithHandle`. The `result` promise settles when
8483
- * the task finishes; `cancel()` evicts a still-pending task from the queue
8484
- * (returns `true`) or signals a request-cancellation flag on a running task
8485
- * (returns `false` `workerpool` itself doesn't support hard-cancel and
8486
- * terminating mid-task is destructive).
8483
+ * the task finishes; `cancel()` performs two-tier cancellation:
8484
+ *
8485
+ * - If still pending in the queue: evict cleanly. Returns `true`.
8486
+ * - If already dispatched: propagate to the underlying
8487
+ * `WorkerpoolPromise.cancel()` so the running worker rejects with
8488
+ * `CancellationError`. Returns `true` if the workerpool promise was
8489
+ * still pending at the moment of cancel; `false` if it already settled.
8487
8490
  */
8488
8491
  interface TaskHandle<R> {
8489
8492
  id: string;
@@ -8534,6 +8537,7 @@ declare class WorkerTaskManager {
8534
8537
  private readonly touchedPoolIds;
8535
8538
  private readonly cancelledTaskIds;
8536
8539
  private readonly handleStatus;
8540
+ private readonly liveExecPromises;
8537
8541
  constructor(opts?: {
8538
8542
  /** Max concurrent tasks across the queue. Default: cpus − 1. */
8539
8543
  concurrency?: number;
package/dist/index.js CHANGED
@@ -3441,6 +3441,10 @@ var init_WorkerTaskManager = __esm({
3441
3441
  touchedPoolIds = /* @__PURE__ */ new Set();
3442
3442
  cancelledTaskIds = /* @__PURE__ */ new Set();
3443
3443
  handleStatus = /* @__PURE__ */ new Map();
3444
+ // Live `pool.exec(...)` promises by task id. Populated when a task starts
3445
+ // running so the handle can call `.cancel()` on the workerpool promise
3446
+ // for mid-execution cancellation. Cleared on completion / failure.
3447
+ liveExecPromises = /* @__PURE__ */ new Map();
3444
3448
  constructor(opts = {}) {
3445
3449
  this.queue = new TaskQueue({
3446
3450
  concurrency: opts.concurrency,
@@ -3480,7 +3484,13 @@ var init_WorkerTaskManager = __esm({
3480
3484
  this.handleStatus.set(id, "running" /* RUNNING */);
3481
3485
  const pool = this.poolManager.getPool(input.workerType, opts.poolConfig);
3482
3486
  this.touchedPoolIds.add(input.workerType);
3483
- return await pool.exec(input.methodName, input.args);
3487
+ const execPromise = pool.exec(input.methodName, input.args);
3488
+ this.liveExecPromises.set(id, execPromise);
3489
+ try {
3490
+ return await execPromise;
3491
+ } finally {
3492
+ this.liveExecPromises.delete(id);
3493
+ }
3484
3494
  }
3485
3495
  };
3486
3496
  const result = this.queue.enqueue(task).then(async (res) => {
@@ -3502,8 +3512,21 @@ var init_WorkerTaskManager = __esm({
3502
3512
  const evicted = this.queue.cancel(id);
3503
3513
  if (evicted) {
3504
3514
  this.handleStatus.set(id, "cancelled" /* CANCELLED */);
3515
+ return true;
3505
3516
  }
3506
- return evicted;
3517
+ const live = this.liveExecPromises.get(id);
3518
+ if (live && typeof live.cancel === "function") {
3519
+ if (live.pending === false) return false;
3520
+ try {
3521
+ live.cancel();
3522
+ this.handleStatus.set(id, "cancelled" /* CANCELLED */);
3523
+ return true;
3524
+ } catch (e) {
3525
+ logger.warn(`[WorkerTaskManager] cancel() on live exec for ${id} threw:`, e);
3526
+ return false;
3527
+ }
3528
+ }
3529
+ return false;
3507
3530
  },
3508
3531
  status: () => this.handleStatus.get(id) ?? "pending" /* PENDING */
3509
3532
  };
@@ -20844,6 +20867,27 @@ CREATE INDEX IF NOT EXISTS idx_entities_project_id ON entities(project_id);
20844
20867
  CREATE INDEX IF NOT EXISTS idx_entities_content_hash ON entities(content_hash);
20845
20868
  CREATE INDEX IF NOT EXISTS idx_entities_tags_gin ON entities USING GIN(tags);
20846
20869
 
20870
+ -- v2.8.0 \u2014 generated tsvector column for full-text search.
20871
+ -- name is weighted A (highest), observations B, tags C. PostgreSQL 12+
20872
+ -- supports GENERATED ALWAYS AS ... STORED; the DO block makes the column
20873
+ -- add idempotent on older + newer servers without requiring CREATE OR
20874
+ -- REPLACE semantics on ALTER.
20875
+ DO $$ BEGIN
20876
+ IF NOT EXISTS (
20877
+ SELECT 1 FROM information_schema.columns
20878
+ WHERE table_name = 'entities' AND column_name = 'fts_vector'
20879
+ ) THEN
20880
+ ALTER TABLE entities ADD COLUMN fts_vector tsvector
20881
+ GENERATED ALWAYS AS (
20882
+ setweight(to_tsvector('english', name), 'A') ||
20883
+ setweight(to_tsvector('english', coalesce(array_to_string(observations, ' '), '')), 'B') ||
20884
+ setweight(to_tsvector('english', coalesce(array_to_string(tags, ' '), '')), 'C')
20885
+ ) STORED;
20886
+ END IF;
20887
+ END $$;
20888
+
20889
+ CREATE INDEX IF NOT EXISTS idx_entities_fts_gin ON entities USING GIN(fts_vector);
20890
+
20847
20891
  CREATE TABLE IF NOT EXISTS relations (
20848
20892
  from_name TEXT NOT NULL,
20849
20893
  to_name TEXT NOT NULL,
@@ -21163,6 +21207,38 @@ var PostgreSQLStorage = class {
21163
21207
  hasRelations(entityName) {
21164
21208
  return (this.outgoingRelations.get(entityName)?.length ?? 0) + (this.incomingRelations.get(entityName)?.length ?? 0) > 0;
21165
21209
  }
21210
+ // ==================== Full-text search ====================
21211
+ /**
21212
+ * tsvector-backed full-text search. Uses `plainto_tsquery` so the input is
21213
+ * free-form (no boolean operator syntax required); ranks via `ts_rank` on
21214
+ * the weighted `fts_vector` column (name × A, observations × B, tags × C).
21215
+ *
21216
+ * Results are ordered by descending score and capped at `options.limit`
21217
+ * (default 50). Empty / whitespace-only queries return `[]` without
21218
+ * issuing a SQL call.
21219
+ *
21220
+ * @example
21221
+ * ```typescript
21222
+ * const matches = await storage.fullTextSearch('authentication flow', { limit: 10 });
21223
+ * // → [{ name: 'AuthService', score: 0.62 }, ...]
21224
+ * ```
21225
+ */
21226
+ async fullTextSearch(query, options = {}) {
21227
+ const trimmed = query.trim();
21228
+ if (trimmed.length === 0) return [];
21229
+ await this.initSchema();
21230
+ const pool = await this.getPool();
21231
+ const limit = options.limit ?? 50;
21232
+ const res = await pool.query(
21233
+ `SELECT name, ts_rank(fts_vector, plainto_tsquery('english', $1))::float AS score
21234
+ FROM entities
21235
+ WHERE fts_vector @@ plainto_tsquery('english', $1)
21236
+ ORDER BY score DESC
21237
+ LIMIT $2`,
21238
+ [trimmed, limit]
21239
+ );
21240
+ return res.rows.map((r) => ({ name: r.name, score: Number(r.score) }));
21241
+ }
21166
21242
  // ==================== Utility ====================
21167
21243
  getFilePath() {
21168
21244
  return this.connectionString;