()
| 82 | } |
| 83 | |
| 84 | run(): void { |
| 85 | // Build deltas from input messages |
| 86 | const deltaA = Index.fromMultiSets<K, V1>( |
| 87 | this.inputAMessages() as Array<MultiSet<[K, V1]>>, |
| 88 | ) |
| 89 | const deltaB = Index.fromMultiSets<K, V2>( |
| 90 | this.inputBMessages() as Array<MultiSet<[K, V2]>>, |
| 91 | ) |
| 92 | |
| 93 | // Early-out if nothing changed |
| 94 | if (deltaA.size === 0 && deltaB.size === 0) return |
| 95 | |
| 96 | const results = new MultiSet<any>() |
| 97 | |
| 98 | // Emit inner results (all modes except anti) |
| 99 | if (this.#mode !== `anti`) { |
| 100 | this.emitInnerResults(deltaA, deltaB, results) |
| 101 | } |
| 102 | |
| 103 | // Emit left outer/anti results |
| 104 | if ( |
| 105 | this.#mode === `left` || |
| 106 | this.#mode === `full` || |
| 107 | this.#mode === `anti` |
| 108 | ) { |
| 109 | this.emitLeftOuterResults(deltaA, deltaB, results) |
| 110 | } |
| 111 | |
| 112 | // Emit right outer results |
| 113 | if (this.#mode === `right` || this.#mode === `full`) { |
| 114 | this.emitRightOuterResults(deltaA, deltaB, results) |
| 115 | } |
| 116 | |
| 117 | // Update state and send results |
| 118 | // IMPORTANT: All emissions use pre-append snapshots of indexA/indexB. |
| 119 | // Now append ALL deltas to indices - this happens unconditionally for every key, |
| 120 | // regardless of whether presence flipped. Consolidated multiplicity tracking is automatic. |
| 121 | this.#indexA.append(deltaA) |
| 122 | this.#indexB.append(deltaB) |
| 123 | |
| 124 | // Send results |
| 125 | if (results.getInner().length > 0) { |
| 126 | this.output.sendData(results) |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | private emitInnerResults( |
| 131 | deltaA: Index<K, V1>, |
nothing calls this directly
no test coverage detected