seer-mcp 0.1.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/.vscode/settings.json +3 -0
- package/LICENSE +176 -0
- package/README.md +272 -0
- package/README_dev.md +199 -0
- package/dist/bundle/ci.d.ts +47 -0
- package/dist/bundle/ci.d.ts.map +1 -0
- package/dist/bundle/ci.js +113 -0
- package/dist/bundle/ci.js.map +1 -0
- package/dist/bundle/contract.d.ts +111 -0
- package/dist/bundle/contract.d.ts.map +1 -0
- package/dist/bundle/contract.js +352 -0
- package/dist/bundle/contract.js.map +1 -0
- package/dist/bundle/export.d.ts +36 -0
- package/dist/bundle/export.d.ts.map +1 -0
- package/dist/bundle/export.js +152 -0
- package/dist/bundle/export.js.map +1 -0
- package/dist/bundle/external.d.ts +66 -0
- package/dist/bundle/external.d.ts.map +1 -0
- package/dist/bundle/external.js +238 -0
- package/dist/bundle/external.js.map +1 -0
- package/dist/bundle/format.d.ts +94 -0
- package/dist/bundle/format.d.ts.map +1 -0
- package/dist/bundle/format.js +42 -0
- package/dist/bundle/format.js.map +1 -0
- package/dist/bundle/import.d.ts +49 -0
- package/dist/bundle/import.d.ts.map +1 -0
- package/dist/bundle/import.js +116 -0
- package/dist/bundle/import.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +1402 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +48 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +284 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +616 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/store.d.ts +1011 -0
- package/dist/db/store.d.ts.map +1 -0
- package/dist/db/store.js +3888 -0
- package/dist/db/store.js.map +1 -0
- package/dist/graph/pagerank.d.ts +9 -0
- package/dist/graph/pagerank.d.ts.map +1 -0
- package/dist/graph/pagerank.js +47 -0
- package/dist/graph/pagerank.js.map +1 -0
- package/dist/indexer/architecture.d.ts +72 -0
- package/dist/indexer/architecture.d.ts.map +1 -0
- package/dist/indexer/architecture.js +112 -0
- package/dist/indexer/architecture.js.map +1 -0
- package/dist/indexer/behavior.d.ts +75 -0
- package/dist/indexer/behavior.d.ts.map +1 -0
- package/dist/indexer/behavior.js +395 -0
- package/dist/indexer/behavior.js.map +1 -0
- package/dist/indexer/boundaries.d.ts +60 -0
- package/dist/indexer/boundaries.d.ts.map +1 -0
- package/dist/indexer/boundaries.js +366 -0
- package/dist/indexer/boundaries.js.map +1 -0
- package/dist/indexer/churn.d.ts +15 -0
- package/dist/indexer/churn.d.ts.map +1 -0
- package/dist/indexer/churn.js +49 -0
- package/dist/indexer/churn.js.map +1 -0
- package/dist/indexer/classify.d.ts +9 -0
- package/dist/indexer/classify.d.ts.map +1 -0
- package/dist/indexer/classify.js +90 -0
- package/dist/indexer/classify.js.map +1 -0
- package/dist/indexer/context.d.ts +176 -0
- package/dist/indexer/context.d.ts.map +1 -0
- package/dist/indexer/context.js +193 -0
- package/dist/indexer/context.js.map +1 -0
- package/dist/indexer/continuity.d.ts +67 -0
- package/dist/indexer/continuity.d.ts.map +1 -0
- package/dist/indexer/continuity.js +288 -0
- package/dist/indexer/continuity.js.map +1 -0
- package/dist/indexer/detectchanges.d.ts +32 -0
- package/dist/indexer/detectchanges.d.ts.map +1 -0
- package/dist/indexer/detectchanges.js +74 -0
- package/dist/indexer/detectchanges.js.map +1 -0
- package/dist/indexer/discovery.d.ts +37 -0
- package/dist/indexer/discovery.d.ts.map +1 -0
- package/dist/indexer/discovery.js +136 -0
- package/dist/indexer/discovery.js.map +1 -0
- package/dist/indexer/externaldeps.d.ts +18 -0
- package/dist/indexer/externaldeps.d.ts.map +1 -0
- package/dist/indexer/externaldeps.js +288 -0
- package/dist/indexer/externaldeps.js.map +1 -0
- package/dist/indexer/freshness.d.ts +48 -0
- package/dist/indexer/freshness.d.ts.map +1 -0
- package/dist/indexer/freshness.js +128 -0
- package/dist/indexer/freshness.js.map +1 -0
- package/dist/indexer/git.d.ts +144 -0
- package/dist/indexer/git.d.ts.map +1 -0
- package/dist/indexer/git.js +444 -0
- package/dist/indexer/git.js.map +1 -0
- package/dist/indexer/index.d.ts +145 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +930 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/modules.d.ts +62 -0
- package/dist/indexer/modules.d.ts.map +1 -0
- package/dist/indexer/modules.js +293 -0
- package/dist/indexer/modules.js.map +1 -0
- package/dist/indexer/preflight.d.ts +154 -0
- package/dist/indexer/preflight.d.ts.map +1 -0
- package/dist/indexer/preflight.js +399 -0
- package/dist/indexer/preflight.js.map +1 -0
- package/dist/indexer/protoScanner.d.ts +34 -0
- package/dist/indexer/protoScanner.d.ts.map +1 -0
- package/dist/indexer/protoScanner.js +133 -0
- package/dist/indexer/protoScanner.js.map +1 -0
- package/dist/indexer/risk.d.ts +115 -0
- package/dist/indexer/risk.d.ts.map +1 -0
- package/dist/indexer/risk.js +194 -0
- package/dist/indexer/risk.js.map +1 -0
- package/dist/indexer/serviceHostScanner.d.ts +25 -0
- package/dist/indexer/serviceHostScanner.d.ts.map +1 -0
- package/dist/indexer/serviceHostScanner.js +95 -0
- package/dist/indexer/serviceHostScanner.js.map +1 -0
- package/dist/indexer/serviceLinks.d.ts +105 -0
- package/dist/indexer/serviceLinks.d.ts.map +1 -0
- package/dist/indexer/serviceLinks.js +509 -0
- package/dist/indexer/serviceLinks.js.map +1 -0
- package/dist/indexer/shapehash.d.ts +98 -0
- package/dist/indexer/shapehash.d.ts.map +1 -0
- package/dist/indexer/shapehash.js +354 -0
- package/dist/indexer/shapehash.js.map +1 -0
- package/dist/indexer/skeleton.d.ts +15 -0
- package/dist/indexer/skeleton.d.ts.map +1 -0
- package/dist/indexer/skeleton.js +136 -0
- package/dist/indexer/skeleton.js.map +1 -0
- package/dist/indexer/symbolhistory.d.ts +41 -0
- package/dist/indexer/symbolhistory.d.ts.map +1 -0
- package/dist/indexer/symbolhistory.js +124 -0
- package/dist/indexer/symbolhistory.js.map +1 -0
- package/dist/indexer/watcher.d.ts +68 -0
- package/dist/indexer/watcher.d.ts.map +1 -0
- package/dist/indexer/watcher.js +179 -0
- package/dist/indexer/watcher.js.map +1 -0
- package/dist/mcp/server.d.ts +80 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +1610 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/parser/index.d.ts +8 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +33 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/languages/cpp.d.ts +3 -0
- package/dist/parser/languages/cpp.d.ts.map +1 -0
- package/dist/parser/languages/cpp.js +350 -0
- package/dist/parser/languages/cpp.js.map +1 -0
- package/dist/parser/languages/csharp.d.ts +3 -0
- package/dist/parser/languages/csharp.d.ts.map +1 -0
- package/dist/parser/languages/csharp.js +239 -0
- package/dist/parser/languages/csharp.js.map +1 -0
- package/dist/parser/languages/go.d.ts +3 -0
- package/dist/parser/languages/go.d.ts.map +1 -0
- package/dist/parser/languages/go.js +259 -0
- package/dist/parser/languages/go.js.map +1 -0
- package/dist/parser/languages/java.d.ts +3 -0
- package/dist/parser/languages/java.d.ts.map +1 -0
- package/dist/parser/languages/java.js +391 -0
- package/dist/parser/languages/java.js.map +1 -0
- package/dist/parser/languages/python.d.ts +3 -0
- package/dist/parser/languages/python.d.ts.map +1 -0
- package/dist/parser/languages/python.js +396 -0
- package/dist/parser/languages/python.js.map +1 -0
- package/dist/parser/languages/rust.d.ts +3 -0
- package/dist/parser/languages/rust.d.ts.map +1 -0
- package/dist/parser/languages/rust.js +159 -0
- package/dist/parser/languages/rust.js.map +1 -0
- package/dist/parser/languages/typescript.d.ts +3 -0
- package/dist/parser/languages/typescript.d.ts.map +1 -0
- package/dist/parser/languages/typescript.js +1442 -0
- package/dist/parser/languages/typescript.js.map +1 -0
- package/dist/parser/parserContext.d.ts +77 -0
- package/dist/parser/parserContext.d.ts.map +1 -0
- package/dist/parser/parserContext.js +354 -0
- package/dist/parser/parserContext.js.map +1 -0
- package/dist/parser/walker.d.ts +81 -0
- package/dist/parser/walker.d.ts.map +1 -0
- package/dist/parser/walker.js +217 -0
- package/dist/parser/walker.js.map +1 -0
- package/dist/parser/worker.d.ts +66 -0
- package/dist/parser/worker.d.ts.map +1 -0
- package/dist/parser/worker.js +129 -0
- package/dist/parser/worker.js.map +1 -0
- package/dist/parser/workerpool.d.ts +107 -0
- package/dist/parser/workerpool.d.ts.map +1 -0
- package/dist/parser/workerpool.js +383 -0
- package/dist/parser/workerpool.js.map +1 -0
- package/dist/scip/format.d.ts +87 -0
- package/dist/scip/format.d.ts.map +1 -0
- package/dist/scip/format.js +31 -0
- package/dist/scip/format.js.map +1 -0
- package/dist/scip/import.d.ts +37 -0
- package/dist/scip/import.d.ts.map +1 -0
- package/dist/scip/import.js +180 -0
- package/dist/scip/import.js.map +1 -0
- package/dist/types.d.ts +392 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/docs/architecture.md +105 -0
- package/docs/benchmarks/methodology.md +134 -0
- package/docs/benchmarks/raw-results.md +71 -0
- package/docs/benchmarks.md +74 -0
- package/docs/cli.md +148 -0
- package/docs/examples/behavior-tests.md +70 -0
- package/docs/examples/change-history.md +85 -0
- package/docs/examples/pre-edit-context.md +81 -0
- package/docs/examples/service-links.md +88 -0
- package/docs/examples.md +80 -0
- package/docs/faq.md +70 -0
- package/docs/internals.md +104 -0
- package/docs/languages.md +70 -0
- package/docs/limits.md +52 -0
- package/docs/mcp.md +199 -0
- package/docs/quickstart.md +119 -0
- package/docs/testing.md +123 -0
- package/docs/tools.md +115 -0
- package/package.json +52 -0
- package/research-codebase.md +578 -0
- package/seer-cli-docs.md +326 -0
- package/seer-master-guide.md +246 -0
- package/src/bundle/ci.ts +141 -0
- package/src/bundle/contract.ts +387 -0
- package/src/bundle/export.ts +175 -0
- package/src/bundle/external.ts +285 -0
- package/src/bundle/format.ts +92 -0
- package/src/bundle/import.ts +157 -0
- package/src/cli/index.ts +1249 -0
- package/src/cli/init.ts +389 -0
- package/src/db/schema.ts +614 -0
- package/src/db/store.ts +4306 -0
- package/src/graph/pagerank.ts +53 -0
- package/src/indexer/architecture.ts +148 -0
- package/src/indexer/behavior.ts +466 -0
- package/src/indexer/boundaries.ts +374 -0
- package/src/indexer/churn.ts +58 -0
- package/src/indexer/classify.ts +96 -0
- package/src/indexer/context.ts +340 -0
- package/src/indexer/continuity.ts +322 -0
- package/src/indexer/detectchanges.ts +94 -0
- package/src/indexer/discovery.ts +176 -0
- package/src/indexer/externaldeps.ts +243 -0
- package/src/indexer/freshness.ts +166 -0
- package/src/indexer/git.ts +453 -0
- package/src/indexer/index.ts +1092 -0
- package/src/indexer/modules.ts +358 -0
- package/src/indexer/preflight.ts +548 -0
- package/src/indexer/protoScanner.ts +147 -0
- package/src/indexer/risk.ts +304 -0
- package/src/indexer/serviceHostScanner.ts +92 -0
- package/src/indexer/serviceLinks.ts +543 -0
- package/src/indexer/shapehash.ts +370 -0
- package/src/indexer/skeleton.ts +169 -0
- package/src/indexer/symbolhistory.ts +172 -0
- package/src/indexer/watcher.ts +206 -0
- package/src/mcp/server.ts +1659 -0
- package/src/parser/index.ts +37 -0
- package/src/parser/languages/cpp.ts +361 -0
- package/src/parser/languages/csharp.ts +235 -0
- package/src/parser/languages/go.ts +259 -0
- package/src/parser/languages/java.ts +382 -0
- package/src/parser/languages/python.ts +370 -0
- package/src/parser/languages/rust.ts +164 -0
- package/src/parser/languages/typescript.ts +1435 -0
- package/src/parser/parserContext.ts +392 -0
- package/src/parser/walker.ts +306 -0
- package/src/parser/worker.ts +181 -0
- package/src/parser/workerpool.ts +448 -0
- package/src/scip/format.ts +83 -0
- package/src/scip/import.ts +216 -0
- package/src/types.ts +457 -0
- package/tests/benchmark-service-links.ts +244 -0
- package/tests/bug-regressions.ts +626 -0
- package/tests/filters.ts +264 -0
- package/tests/fixtures/Counter.tsx +38 -0
- package/tests/fixtures/caller.ts +7 -0
- package/tests/fixtures/collisions.ts +23 -0
- package/tests/fixtures/local_helper.ts +5 -0
- package/tests/fixtures/overloads.java +17 -0
- package/tests/fixtures/remote_helper.ts +4 -0
- package/tests/fixtures/sample.c +15 -0
- package/tests/fixtures/sample.cpp +47 -0
- package/tests/fixtures/sample.cs +62 -0
- package/tests/fixtures/sample.go +68 -0
- package/tests/fixtures/sample.h +30 -0
- package/tests/fixtures/sample.java +85 -0
- package/tests/fixtures/sample.py +46 -0
- package/tests/fixtures/sample.rs +78 -0
- package/tests/fixtures/sample.ts +76 -0
- package/tests/fixtures-service/HttpClients.cs +30 -0
- package/tests/fixtures-service/HttpClients.java +24 -0
- package/tests/fixtures-service/billing.ts +15 -0
- package/tests/fixtures-service/docker-compose.yml +15 -0
- package/tests/fixtures-service/gateway.ts +10 -0
- package/tests/fixtures-service/get_user.ts +11 -0
- package/tests/fixtures-service/graphql_client.ts +63 -0
- package/tests/fixtures-service/graphql_server.ts +30 -0
- package/tests/fixtures-service/grpc_client.go +30 -0
- package/tests/fixtures-service/http_clients.go +23 -0
- package/tests/fixtures-service/http_clients.py +38 -0
- package/tests/fixtures-service/http_clients.ts +49 -0
- package/tests/fixtures-service/k8s/payment-service.yaml +22 -0
- package/tests/fixtures-service/k8s_calls.ts +20 -0
- package/tests/fixtures-service/messaging.ts +87 -0
- package/tests/fixtures-service/trpc_client.ts +39 -0
- package/tests/fixtures-service/trpc_server.ts +39 -0
- package/tests/fixtures-service/user_service.proto +33 -0
- package/tests/fixtures-trackcd/Cargo.toml +11 -0
- package/tests/fixtures-trackcd/SpringController.java +36 -0
- package/tests/fixtures-trackcd/auth_service.ts +19 -0
- package/tests/fixtures-trackcd/complex_module.py +50 -0
- package/tests/fixtures-trackcd/express_app.js +30 -0
- package/tests/fixtures-trackcd/fastapi_app.py +49 -0
- package/tests/fixtures-trackcd/fastify_object_routes.js +32 -0
- package/tests/fixtures-trackcd/go.mod +8 -0
- package/tests/fixtures-trackcd/package.json +15 -0
- package/tests/fixtures-trackcd/requirements.txt +4 -0
- package/tests/fixtures-trackcd/tests/auth_service.test.ts +13 -0
- package/tests/fixtures-tracke/auth/AuthService.ts +23 -0
- package/tests/fixtures-tracke/auth/crypto.ts +7 -0
- package/tests/fixtures-tracke/billing/Billing.ts +20 -0
- package/tests/fixtures-tracke/billing/Invoice.ts +10 -0
- package/tests/fixtures-tracke/billing/server.ts +17 -0
- package/tests/fixtures-tracke/package.json +7 -0
- package/tests/fixtures-tracke/tests/auth.test.ts +23 -0
- package/tests/fixtures-tracke/tests/billing.test.ts +14 -0
- package/tests/fixtures-trackf/package.json +5 -0
- package/tests/fixtures-trackf/src/auth.ts +26 -0
- package/tests/fixtures-trackf/src/handlers.ts +35 -0
- package/tests/fixtures-tracki/billing/routes.ts +12 -0
- package/tests/fixtures-tracki/gateway/client.ts +13 -0
- package/tests/git-features.ts +267 -0
- package/tests/init.ts +141 -0
- package/tests/mcp-jit.ts +130 -0
- package/tests/mcp-smoke.ts +191 -0
- package/tests/mcp-trackcd.ts +169 -0
- package/tests/mcp-tracke.ts +229 -0
- package/tests/mcp-trackf.ts +330 -0
- package/tests/mcp-trackg.ts +219 -0
- package/tests/mcp-tracki.ts +174 -0
- package/tests/mcp-watcher.ts +126 -0
- package/tests/optspec.ts +194 -0
- package/tests/parallel-index.ts +333 -0
- package/tests/parallel-read.ts +125 -0
- package/tests/parallel-recovery.ts +241 -0
- package/tests/perf-callers.ts +145 -0
- package/tests/query-parity.ts +184 -0
- package/tests/query-perf.ts +55 -0
- package/tests/scale-parallel-parity.ts +225 -0
- package/tests/scale-test.ts +523 -0
- package/tests/smoke.ts +396 -0
- package/tests/trackcd.ts +325 -0
- package/tests/tracke-collisions.ts +255 -0
- package/tests/tracke.ts +314 -0
- package/tests/trackf-bugs.ts +406 -0
- package/tests/trackf.ts +390 -0
- package/tests/trackg.ts +1372 -0
- package/tests/tracki-boundaries.ts +202 -0
- package/tests/tracki-continuity.ts +253 -0
- package/tests/tracki-contract-diff.ts +249 -0
- package/tests/tracki-external-bundles.ts +341 -0
- package/tests/tracki-preflight.ts +251 -0
- package/tests/verify-roles.ts +51 -0
- package/tests/worker-parity.ts +286 -0
- package/tests/worker-pool.ts +262 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.walkTree = walkTree;
|
|
4
|
+
exports.fieldText = fieldText;
|
|
5
|
+
exports.firstLine = firstLine;
|
|
6
|
+
/**
|
|
7
|
+
* Walk the tree, tracking the enclosing definition stack so that calls can
|
|
8
|
+
* be attributed to their containing function/method.
|
|
9
|
+
*
|
|
10
|
+
* v4 additions:
|
|
11
|
+
* - For function/method/constructor symbols, computes cyclomatic + cognitive
|
|
12
|
+
* complexity + max nesting depth + LOC by walking the def's subtree once.
|
|
13
|
+
* - Calls `tryExtractRoute` / `tryExtractConfigKey` per node and threads the
|
|
14
|
+
* results back through `FileExtraction.routes` / `.configKeys`.
|
|
15
|
+
*
|
|
16
|
+
* Optional `candidates` parameter: when provided, the walker only invokes the
|
|
17
|
+
* extractor's `tryExtract*` callbacks on nodes whose id is in the set. Tree
|
|
18
|
+
* structure is still fully traversed so the def-stack stays accurate; we just
|
|
19
|
+
* skip the per-node switch on non-candidates. Pass `undefined` (the default)
|
|
20
|
+
* to run as a full baseline walker.
|
|
21
|
+
*/
|
|
22
|
+
function walkTree(root, extractor, candidates) {
|
|
23
|
+
const extraction = {
|
|
24
|
+
language: extractor.languageName,
|
|
25
|
+
definitions: [],
|
|
26
|
+
references: [],
|
|
27
|
+
importedModules: [],
|
|
28
|
+
routes: [],
|
|
29
|
+
configKeys: [],
|
|
30
|
+
serviceCalls: [],
|
|
31
|
+
};
|
|
32
|
+
const defStack = [];
|
|
33
|
+
// One counter-map per nesting level tracks how many times each short name
|
|
34
|
+
// has been pushed as a direct child, so overloads get distinct suffixes.
|
|
35
|
+
const siblingCounts = [new Map()];
|
|
36
|
+
function pushName(name) {
|
|
37
|
+
const counters = siblingCounts[siblingCounts.length - 1];
|
|
38
|
+
const n = counters.get(name) ?? 0;
|
|
39
|
+
counters.set(name, n + 1);
|
|
40
|
+
const disambig = n === 0 ? name : `${name}#${n}`;
|
|
41
|
+
defStack.push(disambig);
|
|
42
|
+
siblingCounts.push(new Map());
|
|
43
|
+
return disambig;
|
|
44
|
+
}
|
|
45
|
+
function popName() {
|
|
46
|
+
defStack.pop();
|
|
47
|
+
siblingCounts.pop();
|
|
48
|
+
}
|
|
49
|
+
// When `candidates` is provided, only nodes whose id is in the set get
|
|
50
|
+
// their tryExtract* callbacks fired. Tree structure is still fully walked
|
|
51
|
+
// so the def-stack remains correct across non-candidate ancestors.
|
|
52
|
+
const useCandidates = candidates !== undefined;
|
|
53
|
+
function walk(node) {
|
|
54
|
+
const isCandidate = useCandidates ? candidates.has(node.id) : true;
|
|
55
|
+
const def = isCandidate ? extractor.tryExtractDefinition(node) : null;
|
|
56
|
+
if (def) {
|
|
57
|
+
// Out-of-line / qualified definitions (e.g. C++ `Vec::dot` defined at
|
|
58
|
+
// namespace scope) carry extra owning-scope segments that aren't on the
|
|
59
|
+
// lexical def stack. Fold them into the local name so the qualified name
|
|
60
|
+
// reflects the true owner, and key overload disambiguation on the full
|
|
61
|
+
// (scope + name) so `Foo::bar` and `Baz::bar` don't collapse together.
|
|
62
|
+
const localName = def.scopePath && def.scopePath.length > 0
|
|
63
|
+
? `${def.scopePath.join('.')}.${def.name}`
|
|
64
|
+
: def.name;
|
|
65
|
+
const disambig = pushName(localName);
|
|
66
|
+
def.qualifiedName =
|
|
67
|
+
defStack.length === 1
|
|
68
|
+
? disambig
|
|
69
|
+
: `${defStack.slice(0, -1).join('.')}.${disambig}`;
|
|
70
|
+
// Compute complexity for behavior-bearing symbols only (kinds where
|
|
71
|
+
// cyclomatic complexity is meaningful).
|
|
72
|
+
if ((def.kind === 'function' || def.kind === 'method' || def.kind === 'constructor') &&
|
|
73
|
+
extractor.branchNodeTypes) {
|
|
74
|
+
const m = measureComplexity(node, extractor.branchNodeTypes, extractor.nestingNodeTypes);
|
|
75
|
+
def.cyclomatic = m.cyclomatic;
|
|
76
|
+
def.cognitive = m.cognitive;
|
|
77
|
+
def.maxNesting = m.maxNesting;
|
|
78
|
+
def.loc = m.loc;
|
|
79
|
+
}
|
|
80
|
+
else if (def.kind === 'function' || def.kind === 'method' || def.kind === 'constructor') {
|
|
81
|
+
// LOC even without branchNodeTypes — cheap and useful.
|
|
82
|
+
def.loc = countNonBlankLines(node);
|
|
83
|
+
}
|
|
84
|
+
extraction.definitions.push(def);
|
|
85
|
+
for (const child of node.children)
|
|
86
|
+
walk(child);
|
|
87
|
+
popName();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const ctxName = isCandidate ? extractor.tryExtractContextName?.(node) : null;
|
|
91
|
+
if (ctxName) {
|
|
92
|
+
defStack.push(ctxName);
|
|
93
|
+
siblingCounts.push(new Map());
|
|
94
|
+
for (const child of node.children)
|
|
95
|
+
walk(child);
|
|
96
|
+
popName();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (isCandidate) {
|
|
100
|
+
// Routes are checked before calls because route registrations are
|
|
101
|
+
// themselves call expressions in JS frameworks (`app.get("/x", handler)`).
|
|
102
|
+
// Returning routes doesn't prevent the call from also being recorded —
|
|
103
|
+
// the route registration call is itself useful in the call graph.
|
|
104
|
+
const routes = extractor.tryExtractRoute?.(node);
|
|
105
|
+
let wasRoute = false;
|
|
106
|
+
if (routes && routes.length > 0) {
|
|
107
|
+
for (const r of routes)
|
|
108
|
+
extraction.routes.push(r);
|
|
109
|
+
wasRoute = true;
|
|
110
|
+
}
|
|
111
|
+
const configKey = extractor.tryExtractConfigKey?.(node);
|
|
112
|
+
if (configKey) {
|
|
113
|
+
configKey.callerName = defStack.length > 0 ? defStack.join('.') : '';
|
|
114
|
+
extraction.configKeys.push(configKey);
|
|
115
|
+
}
|
|
116
|
+
// Skip service-call extraction on nodes that were already classified as
|
|
117
|
+
// route registrations — `app.post('/api/x', handler)` is a server-side
|
|
118
|
+
// mount, not a client dialing /api/x. Without this guard the resolver
|
|
119
|
+
// would see two service_calls for every route and link the route handler
|
|
120
|
+
// to its own registration site.
|
|
121
|
+
const svcCalls = !wasRoute ? extractor.tryExtractServiceCalls?.(node) : null;
|
|
122
|
+
if (svcCalls && svcCalls.length > 0) {
|
|
123
|
+
const callerName = defStack.length > 0 ? defStack.join('.') : '';
|
|
124
|
+
for (const sc of svcCalls) {
|
|
125
|
+
sc.callerName = sc.callerName ?? callerName;
|
|
126
|
+
extraction.serviceCalls.push(sc);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const callee = extractor.tryExtractCallName(node);
|
|
130
|
+
if (callee) {
|
|
131
|
+
const callerName = defStack.length > 0 ? defStack.join('.') : '';
|
|
132
|
+
extraction.references.push({
|
|
133
|
+
calleeName: callee,
|
|
134
|
+
callerName,
|
|
135
|
+
kind: 'call',
|
|
136
|
+
line: node.startPosition.row,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const importPath = extractor.tryExtractImport(node);
|
|
140
|
+
if (importPath) {
|
|
141
|
+
extraction.importedModules.push(importPath);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
for (const child of node.children)
|
|
145
|
+
walk(child);
|
|
146
|
+
}
|
|
147
|
+
walk(root);
|
|
148
|
+
return extraction;
|
|
149
|
+
}
|
|
150
|
+
function fieldText(node, fieldName) {
|
|
151
|
+
return node.childForFieldName(fieldName)?.text ?? null;
|
|
152
|
+
}
|
|
153
|
+
function firstLine(node, maxLen = 120) {
|
|
154
|
+
const text = node.text;
|
|
155
|
+
const end = text.indexOf('\n');
|
|
156
|
+
const line = end === -1 ? text : text.slice(0, end);
|
|
157
|
+
return line.trim().slice(0, maxLen);
|
|
158
|
+
}
|
|
159
|
+
// ── Complexity computation ─────────────────────────────────────────────────────
|
|
160
|
+
/**
|
|
161
|
+
* Walk a function/method subtree once and compute:
|
|
162
|
+
* - cyclomatic: 1 + count of branch nodes (if/while/for/case/catch/&&/||/?:)
|
|
163
|
+
* - cognitive: branch count + extra penalty for nesting depth
|
|
164
|
+
* - maxNesting: deepest nesting level reached inside the def body
|
|
165
|
+
* - loc: non-blank lines in the def's source span
|
|
166
|
+
*
|
|
167
|
+
* Definitions of "branch" come from the extractor — different grammars name
|
|
168
|
+
* the same constructs differently (Python `if_statement` vs JS `if_statement`
|
|
169
|
+
* are spelled identically, but Go has `if_statement` + `expression_switch_statement`).
|
|
170
|
+
*/
|
|
171
|
+
function measureComplexity(defNode, branchTypes, nestingTypes) {
|
|
172
|
+
let cyclomatic = 1;
|
|
173
|
+
let cognitive = 0;
|
|
174
|
+
let maxNesting = 0;
|
|
175
|
+
const nesting = nestingTypes ?? branchTypes;
|
|
176
|
+
function visit(n, depth) {
|
|
177
|
+
if (n === defNode) {
|
|
178
|
+
for (const child of n.children)
|
|
179
|
+
visit(child, 0);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
let newDepth = depth;
|
|
183
|
+
if (branchTypes.has(n.type)) {
|
|
184
|
+
cyclomatic++;
|
|
185
|
+
// Cognitive: +1 + current depth for every branch (so deeply nested
|
|
186
|
+
// branches cost more). This matches Sonar's rough scoring.
|
|
187
|
+
cognitive += 1 + depth;
|
|
188
|
+
}
|
|
189
|
+
if (nesting.has(n.type)) {
|
|
190
|
+
newDepth = depth + 1;
|
|
191
|
+
if (newDepth > maxNesting)
|
|
192
|
+
maxNesting = newDepth;
|
|
193
|
+
}
|
|
194
|
+
for (const child of n.children)
|
|
195
|
+
visit(child, newDepth);
|
|
196
|
+
}
|
|
197
|
+
visit(defNode, 0);
|
|
198
|
+
const loc = countNonBlankLines(defNode);
|
|
199
|
+
return { cyclomatic, cognitive, maxNesting, loc };
|
|
200
|
+
}
|
|
201
|
+
function countNonBlankLines(node) {
|
|
202
|
+
const text = node.text;
|
|
203
|
+
if (!text)
|
|
204
|
+
return 0;
|
|
205
|
+
let count = 0;
|
|
206
|
+
let start = 0;
|
|
207
|
+
for (let i = 0; i <= text.length; i++) {
|
|
208
|
+
if (i === text.length || text.charCodeAt(i) === 10) {
|
|
209
|
+
const line = text.slice(start, i);
|
|
210
|
+
if (line.trim().length > 0)
|
|
211
|
+
count++;
|
|
212
|
+
start = i + 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return count;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=walker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/parser/walker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { FileExtraction, Language } from '../types.js';
|
|
2
|
+
export type WorkerInput = {
|
|
3
|
+
kind: 'parse';
|
|
4
|
+
seq: number;
|
|
5
|
+
abs: string;
|
|
6
|
+
lang: Language;
|
|
7
|
+
/** Known DB hash for this file; if the just-read hash matches, skip parse. */
|
|
8
|
+
expectedHash: string | null;
|
|
9
|
+
/** 0 = no cap. */
|
|
10
|
+
maxFileBytes: number;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'shutdown';
|
|
13
|
+
};
|
|
14
|
+
export type WorkerOutput =
|
|
15
|
+
/** Posted exactly once, after `Parser.init()` has succeeded. */
|
|
16
|
+
{
|
|
17
|
+
kind: 'ready';
|
|
18
|
+
}
|
|
19
|
+
/** Read + hashed + parsed successfully. */
|
|
20
|
+
| {
|
|
21
|
+
kind: 'parsed';
|
|
22
|
+
seq: number;
|
|
23
|
+
hash: string;
|
|
24
|
+
lines: number;
|
|
25
|
+
size: number;
|
|
26
|
+
/** Cumulative ParserContext reset count in this worker isolate. */
|
|
27
|
+
wasmResets: number;
|
|
28
|
+
extraction: FileExtraction;
|
|
29
|
+
}
|
|
30
|
+
/** Read + hashed but parse returned null (tree-sitter gave up). */
|
|
31
|
+
| {
|
|
32
|
+
kind: 'parse-error';
|
|
33
|
+
seq: number;
|
|
34
|
+
hash: string;
|
|
35
|
+
lines: number;
|
|
36
|
+
size: number;
|
|
37
|
+
wasmResets: number;
|
|
38
|
+
}
|
|
39
|
+
/** Read + hash matched `expectedHash` — no parse performed. */
|
|
40
|
+
| {
|
|
41
|
+
kind: 'cached';
|
|
42
|
+
seq: number;
|
|
43
|
+
hash: string;
|
|
44
|
+
lines: number;
|
|
45
|
+
size: number;
|
|
46
|
+
wasmResets: number;
|
|
47
|
+
}
|
|
48
|
+
/** stat() reported size > maxFileBytes; file was not read. */
|
|
49
|
+
| {
|
|
50
|
+
kind: 'too-large';
|
|
51
|
+
seq: number;
|
|
52
|
+
size: number;
|
|
53
|
+
wasmResets: number;
|
|
54
|
+
}
|
|
55
|
+
/** readFile or stat threw. */
|
|
56
|
+
| {
|
|
57
|
+
kind: 'io-error';
|
|
58
|
+
seq: number;
|
|
59
|
+
error: string;
|
|
60
|
+
wasmResets: number;
|
|
61
|
+
}
|
|
62
|
+
/** Posted just before the worker calls process.exit(0) in response to shutdown. */
|
|
63
|
+
| {
|
|
64
|
+
kind: 'shutdown-ack';
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/parser/worker.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK5D,MAAM,MAAM,WAAW,GACnB;IACE,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;IACf,8EAA8E;IAC9E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,GACD;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,MAAM,MAAM,YAAY;AACtB,gEAAgE;AAC9D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE;AACnB,2CAA2C;GACzC;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,cAAc,CAAC;CAC5B;AACH,mEAAmE;GACjE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AACrG,+DAA+D;GAC7D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AAChG,8DAA8D;GAC5D;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AACtE,8BAA8B;GAC5B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AACtE,mFAAmF;GACjF;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/**
|
|
7
|
+
* Parser worker — runs in its own V8 isolate via `worker_threads`.
|
|
8
|
+
*
|
|
9
|
+
* Each worker owns ONE `ParserContext` (its own WASM heap + grammar cache).
|
|
10
|
+
* Workers do their own file I/O so the main thread keeps no prefetcher,
|
|
11
|
+
* just dispatches paths and drains results.
|
|
12
|
+
*
|
|
13
|
+
* Protocol (see `WorkerInput` / `WorkerOutput`):
|
|
14
|
+
* main → worker: { kind: 'parse', seq, abs, lang, expectedHash, maxFileBytes }
|
|
15
|
+
* main → worker: { kind: 'shutdown' }
|
|
16
|
+
* worker → main: { kind: 'ready' } (once, on startup)
|
|
17
|
+
* worker → main: { kind: 'parsed' | 'parse-error' | 'cached' | 'too-large' | 'io-error', seq, wasmResets, ... }
|
|
18
|
+
* worker → main: { kind: 'shutdown-ack' } (just before exit)
|
|
19
|
+
*
|
|
20
|
+
* The worker is intentionally dumb about WHAT to do with extractions — it
|
|
21
|
+
* just returns the FileExtraction. All DB writes happen on the main thread.
|
|
22
|
+
*
|
|
23
|
+
* Failure isolation: a WASM abort inside this worker is contained to this
|
|
24
|
+
* isolate. The `ParserContext` already auto-resets the WASM runtime after
|
|
25
|
+
* three consecutive failures. If the worker crashes outright the pool
|
|
26
|
+
* detects the exit and requeues the inflight job (subject to a per-job
|
|
27
|
+
* attempt limit so a poison file can't crash workers forever).
|
|
28
|
+
*/
|
|
29
|
+
const worker_threads_1 = require("worker_threads");
|
|
30
|
+
const fs_1 = __importDefault(require("fs"));
|
|
31
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
32
|
+
const parserContext_js_1 = require("./parserContext.js");
|
|
33
|
+
// ── Worker bootstrap ─────────────────────────────────────────────────────────
|
|
34
|
+
if (!worker_threads_1.parentPort) {
|
|
35
|
+
throw new Error('parser/worker.ts must be loaded via worker_threads, not require()');
|
|
36
|
+
}
|
|
37
|
+
const port = worker_threads_1.parentPort;
|
|
38
|
+
const ctx = new parserContext_js_1.ParserContext();
|
|
39
|
+
// Test-only crash hook. When `SEER_WORKER_TEST_CRASH_ON=<substr>` is set in
|
|
40
|
+
// the environment of the spawning process, the worker hard-crashes on any
|
|
41
|
+
// parse job whose `abs` contains `<substr>`. Used by `tests/parallel-recovery.ts`
|
|
42
|
+
// to verify that pool crash recovery (respawn + retry, attempt limit) works.
|
|
43
|
+
// Production never sets this variable.
|
|
44
|
+
const TEST_CRASH_ON = (typeof process !== 'undefined' && process.env && process.env.SEER_WORKER_TEST_CRASH_ON)
|
|
45
|
+
? process.env.SEER_WORKER_TEST_CRASH_ON
|
|
46
|
+
: null;
|
|
47
|
+
// Test-only reset hook. It lets worker-pool/indexer tests verify reset-count
|
|
48
|
+
// aggregation deterministically without inducing a real tree-sitter WASM abort.
|
|
49
|
+
// Production never sets this variable.
|
|
50
|
+
const TEST_FAKE_WASM_RESET_ON = (typeof process !== 'undefined' && process.env && process.env.SEER_WORKER_TEST_FAKE_WASM_RESET_ON)
|
|
51
|
+
? process.env.SEER_WORKER_TEST_FAKE_WASM_RESET_ON
|
|
52
|
+
: null;
|
|
53
|
+
let testExtraWasmResets = 0;
|
|
54
|
+
function post(msg) {
|
|
55
|
+
port.postMessage(msg);
|
|
56
|
+
}
|
|
57
|
+
function sha256Short(content) {
|
|
58
|
+
return crypto_1.default.createHash('sha256').update(content, 'utf8').digest('hex').slice(0, 16);
|
|
59
|
+
}
|
|
60
|
+
function wasmResetCount() {
|
|
61
|
+
return ctx.wasmResetCount() + testExtraWasmResets;
|
|
62
|
+
}
|
|
63
|
+
async function handleParse(job) {
|
|
64
|
+
const { seq, abs, lang, expectedHash, maxFileBytes } = job;
|
|
65
|
+
// Test-only crash hook.
|
|
66
|
+
if (TEST_CRASH_ON && abs.includes(TEST_CRASH_ON)) {
|
|
67
|
+
// Hard-exit so the parent observes a non-zero `exit` event — the pool's
|
|
68
|
+
// crash path runs and we exercise respawn + retry + attempt-limit.
|
|
69
|
+
process.exit(13);
|
|
70
|
+
}
|
|
71
|
+
if (TEST_FAKE_WASM_RESET_ON && abs.includes(TEST_FAKE_WASM_RESET_ON)) {
|
|
72
|
+
testExtraWasmResets++;
|
|
73
|
+
}
|
|
74
|
+
// Size gate: only stat when a cap is in force, so the default-no-cap path
|
|
75
|
+
// is one syscall (the readFile) per file.
|
|
76
|
+
if (maxFileBytes > 0) {
|
|
77
|
+
let size;
|
|
78
|
+
try {
|
|
79
|
+
size = (await fs_1.default.promises.stat(abs)).size;
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
post({ kind: 'io-error', seq, error: String(err?.message ?? err), wasmResets: wasmResetCount() });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (size > maxFileBytes) {
|
|
86
|
+
post({ kind: 'too-large', seq, size, wasmResets: wasmResetCount() });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
let content;
|
|
91
|
+
try {
|
|
92
|
+
content = await fs_1.default.promises.readFile(abs, 'utf8');
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
post({ kind: 'io-error', seq, error: String(err?.message ?? err), wasmResets: wasmResetCount() });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const hash = sha256Short(content);
|
|
99
|
+
const lines = content.split('\n').length;
|
|
100
|
+
const size = Buffer.byteLength(content, 'utf8');
|
|
101
|
+
// Cache hit — main thread gave us a known hash for this path, and it
|
|
102
|
+
// matches. Skip parsing entirely; main thread will still upsertFileWithCache
|
|
103
|
+
// (so touchedFileIds is updated and pruneFilesNotIn does not delete this).
|
|
104
|
+
if (expectedHash !== null && hash === expectedHash) {
|
|
105
|
+
post({ kind: 'cached', seq, hash, lines, size, wasmResets: wasmResetCount() });
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const extraction = await ctx.parseFile(content, abs, lang);
|
|
109
|
+
if (!extraction) {
|
|
110
|
+
post({ kind: 'parse-error', seq, hash, lines, size, wasmResets: wasmResetCount() });
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
post({ kind: 'parsed', seq, hash, lines, size, wasmResets: wasmResetCount(), extraction });
|
|
114
|
+
}
|
|
115
|
+
port.on('message', (msg) => {
|
|
116
|
+
if (msg.kind === 'shutdown') {
|
|
117
|
+
post({ kind: 'shutdown-ack' });
|
|
118
|
+
// Give the message a tick to flush before exit.
|
|
119
|
+
setImmediate(() => process.exit(0));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Errors inside handleParse must not crash the worker — they're caught,
|
|
123
|
+
// logged through the protocol, and the worker stays alive for the next job.
|
|
124
|
+
handleParse(msg).catch(err => {
|
|
125
|
+
post({ kind: 'io-error', seq: msg.seq, error: `worker internal: ${String(err?.message ?? err)}`, wasmResets: wasmResetCount() });
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
post({ kind: 'ready' });
|
|
129
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/parser/worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Language } from '../types.js';
|
|
2
|
+
import type { WorkerOutput } from './worker.js';
|
|
3
|
+
export interface WorkerPoolOptions {
|
|
4
|
+
/** Number of worker threads. Defaults to min(8, max(1, availableParallelism()-1)). */
|
|
5
|
+
jobs?: number;
|
|
6
|
+
/** Path to the compiled worker .js. Defaults to dist/parser/worker.js next to this module. */
|
|
7
|
+
workerPath?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Max gap between the head seq (next to drain) and any dispatched seq.
|
|
10
|
+
* Bounds the out-of-order buffer at `maxLag` results in memory.
|
|
11
|
+
* Default: `jobs * 4`.
|
|
12
|
+
*/
|
|
13
|
+
maxLag?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Max times the same seq can be reattempted after a worker crash before
|
|
16
|
+
* we give up and mark it parse-error. Defaults to 3. (One legitimate try +
|
|
17
|
+
* two retries through respawned workers.)
|
|
18
|
+
*/
|
|
19
|
+
maxAttempts?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface WorkItem {
|
|
22
|
+
abs: string;
|
|
23
|
+
lang: Language;
|
|
24
|
+
/** Known DB hash for this file (null if no DB row). */
|
|
25
|
+
expectedHash: string | null;
|
|
26
|
+
/** Per-file byte cap. 0 = no cap. */
|
|
27
|
+
maxFileBytes: number;
|
|
28
|
+
}
|
|
29
|
+
/** What the consumer callback receives. `result` is one of the worker output kinds (minus the lifecycle ones). */
|
|
30
|
+
export type PoolResult = Extract<WorkerOutput, {
|
|
31
|
+
kind: 'parsed';
|
|
32
|
+
}> | Extract<WorkerOutput, {
|
|
33
|
+
kind: 'parse-error';
|
|
34
|
+
}> | Extract<WorkerOutput, {
|
|
35
|
+
kind: 'cached';
|
|
36
|
+
}> | Extract<WorkerOutput, {
|
|
37
|
+
kind: 'too-large';
|
|
38
|
+
}> | Extract<WorkerOutput, {
|
|
39
|
+
kind: 'io-error';
|
|
40
|
+
}>;
|
|
41
|
+
export type ResultCallback = (seq: number, result: PoolResult, item: WorkItem) => void | Promise<void>;
|
|
42
|
+
export declare function defaultWorkerPath(): string;
|
|
43
|
+
export declare class WorkerPool {
|
|
44
|
+
private readonly workerPath;
|
|
45
|
+
private readonly maxLag;
|
|
46
|
+
private readonly maxAttempts;
|
|
47
|
+
private readonly _jobs;
|
|
48
|
+
private workers;
|
|
49
|
+
private idle;
|
|
50
|
+
private nextWorkerId;
|
|
51
|
+
/** Sequence number of the next result we expect to deliver via the callback. */
|
|
52
|
+
private headSeq;
|
|
53
|
+
/** Total jobs in the current dispatch. */
|
|
54
|
+
private totalJobs;
|
|
55
|
+
/** Next seq to send to a worker. */
|
|
56
|
+
private nextDispatchSeq;
|
|
57
|
+
/** seq → WorkItem (for the entire dispatch). */
|
|
58
|
+
private items;
|
|
59
|
+
/** seq → attempt count. */
|
|
60
|
+
private attempts;
|
|
61
|
+
/** Out-of-order buffer for seq > headSeq. */
|
|
62
|
+
private buffered;
|
|
63
|
+
/** Awaiting-worker queue: seqs that need to be dispatched but no worker is free. */
|
|
64
|
+
private pendingDispatch;
|
|
65
|
+
/** Currently active dispatch — null when idle. */
|
|
66
|
+
private active;
|
|
67
|
+
/**
|
|
68
|
+
* Synchronous flag set the moment `dispatch()` is entered. Prevents two
|
|
69
|
+
* synchronous `dispatch()` calls from both passing the `if (this.active)`
|
|
70
|
+
* guard before the first reaches its `await this.ready()`. `this.active`
|
|
71
|
+
* itself is set after that await, so it can't be the only guard.
|
|
72
|
+
*/
|
|
73
|
+
private dispatching;
|
|
74
|
+
/** A rolling promise chain so the consumer callback is invoked strictly serially. */
|
|
75
|
+
private callbackChain;
|
|
76
|
+
private _wasmResets;
|
|
77
|
+
private terminated;
|
|
78
|
+
constructor(opts?: WorkerPoolOptions);
|
|
79
|
+
/** Number of workers actually spawned (after `ready()`). */
|
|
80
|
+
get jobs(): number;
|
|
81
|
+
/** Total worker-local ParserContext resets observed across this pool. */
|
|
82
|
+
wasmResetCount(): number;
|
|
83
|
+
/** Spawn workers and wait for all of them to post `ready`. */
|
|
84
|
+
ready(): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Dispatch every WorkItem to the pool. The callback is invoked exactly once
|
|
87
|
+
* per item, in input order, regardless of which worker finished it.
|
|
88
|
+
*
|
|
89
|
+
* Resolves when every item has been delivered to the callback. Rejects if
|
|
90
|
+
* the pool is terminated mid-dispatch.
|
|
91
|
+
*/
|
|
92
|
+
dispatch(items: WorkItem[], onResult: ResultCallback): Promise<void>;
|
|
93
|
+
/** Shutdown: send 'shutdown' to each worker, await all exits. */
|
|
94
|
+
shutdown(): Promise<void>;
|
|
95
|
+
/** Hammer: force-terminate all workers. Use only when shutdown() can't. */
|
|
96
|
+
terminate(): Promise<void>;
|
|
97
|
+
/** Pump dispatch + drain until either no work is left or no slack remains. */
|
|
98
|
+
private pump;
|
|
99
|
+
private sendJob;
|
|
100
|
+
private spawnWorker;
|
|
101
|
+
private respawnWorker;
|
|
102
|
+
private onWorkerCrash;
|
|
103
|
+
private onWorkerMessage;
|
|
104
|
+
private deliver;
|
|
105
|
+
private invokeCallback;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=workerpool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workerpool.d.ts","sourceRoot":"","sources":["../../src/parser/workerpool.ts"],"names":[],"mappings":"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"}
|