(filePath: string, content: string, stats: fs.Stats, result: ExtractionResult)
| 1706 | const commitYield = createYielder(); |
| 1707 | |
| 1708 | const storeResult = async (filePath: string, content: string, stats: fs.Stats, result: ExtractionResult): Promise<void> => { |
| 1709 | processed++; |
| 1710 | |
| 1711 | // WAL hard-cap backstop: between files (never mid-transaction), pause |
| 1712 | // the store until the off-thread checkpoint catches up. Resolves to |
| 1713 | // null in the normal case — a single size check, no cost. |
| 1714 | const bp = walBackpressure?.(); |
| 1715 | if (bp) await bp; |
| 1716 | |
| 1717 | // Kernel deferred-decode results carry table sizes in kernelCounts |
| 1718 | // (their object arrays are empty — decode happens at the store). |
| 1719 | const nodeCount = result.kernelCounts?.nodes ?? result.nodes.length; |
| 1720 | const edgeCount = result.kernelCounts?.edges ?? result.edges.length; |
| 1721 | |
| 1722 | // Store: on the writer thread when active (fresh DB — bundles applied |
| 1723 | // in the same file order this chain dispatches them), else on the main |
| 1724 | // thread (SQLite connections are per-thread). |
| 1725 | if (nodeCount > 0 || result.errors.length === 0) { |
| 1726 | const language = detectLanguage(filePath, content, overrides); |
| 1727 | if (storeWriter) { |
| 1728 | if (result.kernelBuffers) { |
| 1729 | // Buffers go to the writer as-is; the worker decodes + finalizes. |
| 1730 | // The main thread's only per-file work stays O(1) + the content hash. |
| 1731 | storeWriter.send({ |
| 1732 | kernel: true, |
| 1733 | filePath, |
| 1734 | language, |
| 1735 | buffers: result.kernelBuffers, |
| 1736 | file: this.buildFileRecord(filePath, content, language, stats, nodeCount, result.errors), |
| 1737 | }); |
| 1738 | } else { |
| 1739 | storeWriter.send(this.buildFreshStoreBundle(filePath, content, language, stats, result)); |
| 1740 | } |
| 1741 | await storeWriter.waitBelow(STORE_WRITER_WINDOW); |
| 1742 | } else { |
| 1743 | const materialized = materializeKernelResult(result, filePath, language); |
| 1744 | await this.storeExtractionResult(filePath, content, language, stats, materialized, commitYield); |
| 1745 | } |
| 1746 | } |
| 1747 | |
| 1748 | if (result.errors.length > 0) { |
| 1749 | for (const err of result.errors) { |
| 1750 | if (!err.filePath) err.filePath = filePath; |
| 1751 | } |
| 1752 | errors.push(...result.errors); |
| 1753 | } |
| 1754 | |
| 1755 | if (nodeCount > 0) { |
| 1756 | filesIndexed++; |
| 1757 | totalNodes += nodeCount; |
| 1758 | totalEdges += edgeCount; |
| 1759 | } else if (result.errors.some((e) => e.severity === 'error')) { |
| 1760 | filesErrored++; |
| 1761 | } else { |
| 1762 | // Files with no symbols but no errors (yaml, twig, properties) are |
| 1763 | // tracked at the file level — count them as indexed so the CLI doesn't |
| 1764 | // misleadingly report "No files found to index". |
| 1765 | const lang = detectLanguage(filePath, content, overrides); |
nothing calls this directly
no test coverage detected