mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-19 16:55:02 +02:00
Ports the measured DB-layer hardening from #30294 onto the node content search, and closes two correctness gaps: 1. Sharing as EXISTS, not `workflow.id IN (subquery)`. The IN form makes SQLite drive from shared_workflow and sort every LIKE match in a temp B-tree, discarding the updatedAt index (measured on a 20k corpus in #30294; plan-asserted there in node-search-variants.perf.ts). 2. Index on workflow_entity.updatedAt (migration AddUpdatedAtIndexToWorkflowEntity1786525332822 + entity mirror). The query orders by updatedAt and stops at the limit; without the index every keystroke sorts the whole table (149ms -> 0.9ms at 20k). The migration was already registered in the generated migration index on this branch but the file itself was never committed. 3. Keyset scan instead of a fixed 500-candidate cap. The SQL pre-filter matches the raw JSON blob - node ids, webhook ids, positions - which the in-memory matcher deliberately skips, so a fixed cap let blob-only false positives displace real hits and silently return nothing. The service now batches 100 candidates on an (updatedAt, id) cursor (id tiebreak: updatedAt is not unique) until the result list fills, candidates run out, or a 2000-workflow safety rail stops pathological queries. The cursor is a row-value comparison, NOT the equivalent 'a < x OR (a = x AND b < y)': the OR form makes SQLite pick a MULTI-INDEX OR plan that re-materialises per batch (measured 3.5s vs 96ms per search at 20k in #30294). Credential names are matched too (new 'credentials' field, ranked last): they appear in the serialized workflow, so the pre-filter matches them, and without an in-memory counterpart a credential-name query only ever produced false positives - the most realistic trigger for the empty-results bug. Also ports the Postgres planner hint (SET LOCAL enable_seqscan = off) from #30294: Postgres cannot estimate '%...%' selectivity and otherwise seq-scans + top-N sorts instead of walking the index (75ms -> 1ms). Deliberately not ported from #30294 (yet): the pLimit(1) concurrency gate + per-user rate limiter, and the performance benchmark suite. Verified: matcher 40/40, service unit 19/19, integration 22/22 on both SQLite and Postgres 16; typecheck and lint clean across db, cli, workflow, api-types and editor-ui; editor-ui composable tests 24/24. |
||
|---|---|---|
| .. | ||
| agents | ||
| ai-node-sdk | ||
| ai-utilities | ||
| ai-workflow-builder.ee | ||
| api-types | ||
| backend-common | ||
| backend-network | ||
| backend-test-utils | ||
| benchmark | ||
| blob-storage | ||
| chat-hub | ||
| cli | ||
| client-oauth2 | ||
| codemirror-lang | ||
| codemirror-lang-html | ||
| codemirror-lang-sql | ||
| computer-use | ||
| config | ||
| constants | ||
| crdt | ||
| create-node | ||
| db | ||
| decorators | ||
| di | ||
| engine | ||
| errors | ||
| eslint-config | ||
| eslint-plugin-community-nodes | ||
| expression-runtime | ||
| extension-sdk | ||
| imap | ||
| instance-ai | ||
| json-schema-to-zod | ||
| local-gateway | ||
| mcp-apps | ||
| mcp-browser | ||
| mcp-browser-extension | ||
| node-cli | ||
| node-engine-compatibility | ||
| nodes-langchain | ||
| permissions | ||
| scan-community-package | ||
| scheduler | ||
| stylelint-config | ||
| syslog-client | ||
| task-runner | ||
| task-runner-python | ||
| telemetry | ||
| tournament | ||
| typeorm | ||
| typescript-config | ||
| utils | ||
| vitest-config | ||
| workflow-sdk | ||