@decaf-ts/utils 0.9.6 → 0.10.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.
@@ -26,7 +26,7 @@ export * from "./writers";
26
26
  * @const VERSION
27
27
  * @memberOf module:utils
28
28
  */
29
- export declare const VERSION = "0.9.5";
29
+ export declare const VERSION = "0.10.0";
30
30
  /**
31
31
  * @description Represents the current version of the module.
32
32
  * @summary Stores the version for the @decaf-ts/utils package. The build replaces
package/lib/esm/index.js CHANGED
@@ -26,7 +26,7 @@ export * from "./writers/index.js";
26
26
  * @const VERSION
27
27
  * @memberOf module:utils
28
28
  */
29
- export const VERSION = "0.9.5";
29
+ export const VERSION = "0.10.0";
30
30
  /**
31
31
  * @description Represents the current version of the module.
32
32
  * @summary Stores the version for the @decaf-ts/utils package. The build replaces
@@ -0,0 +1,42 @@
1
+ import { LoggedClass } from "@decaf-ts/logging";
2
+ import { TestReporter } from "./TestReporter";
3
+ type LogStore = Record<number, string[]>;
4
+ export interface ParsedLog {
5
+ timestamp: number;
6
+ child: string;
7
+ action: string;
8
+ }
9
+ export interface ComparerResult {
10
+ consumer: ParsedLog[];
11
+ producer: ParsedLog[];
12
+ }
13
+ type Comparer = (consumerData: LogStore, producerData: LogStore) => Promise<ComparerResult>;
14
+ type ConsumerHandler = (identifier: number, ...args: unknown[]) => unknown | Promise<unknown>;
15
+ export declare const defaultComparer: Comparer;
16
+ export interface ReportingComparerOptions {
17
+ reporter?: TestReporter;
18
+ testCase?: string;
19
+ referencePrefix?: string;
20
+ }
21
+ export declare const reportingComparer: (consumerData: LogStore, producerData: LogStore, options?: ReportingComparerOptions) => Promise<ComparerResult>;
22
+ export declare class ConsumerRunner extends LoggedClass {
23
+ private readonly action;
24
+ private readonly handler;
25
+ private readonly comparerHandle;
26
+ private forkedCache;
27
+ private consumerResults;
28
+ private producerResults;
29
+ private childExitPromises;
30
+ private completionTriggered;
31
+ private activeHandlers;
32
+ constructor(action: string, consumerHandler: ConsumerHandler, compareHandler?: Comparer);
33
+ private reset;
34
+ private waitForChildExit;
35
+ private store;
36
+ private recordConsumer;
37
+ private isProducerComplete;
38
+ private isConsumerComplete;
39
+ private terminateChildren;
40
+ run(count: number, timeout: number | undefined, times: number, random: boolean | undefined): Promise<ComparerResult>;
41
+ }
42
+ export {};
@@ -0,0 +1,316 @@
1
+ import { fork } from "node:child_process";
2
+ import { join } from "node:path";
3
+ import { LoggedClass } from "@decaf-ts/logging";
4
+ import { TestReporter } from "./TestReporter.js";
5
+ const parseData = (data) => {
6
+ const [timestamp, , child, action] = data.split(" - ");
7
+ return {
8
+ timestamp: parseInt(timestamp, 10),
9
+ child,
10
+ action,
11
+ };
12
+ };
13
+ export const defaultComparer = async (consumerData, producerData) => {
14
+ const sortedConsumerData = Object.keys(consumerData)
15
+ .reduce((accum, key) => {
16
+ const identifier = Number(key);
17
+ const entries = consumerData[identifier] ?? [];
18
+ accum.push(...entries.map((entry) => parseData(entry)));
19
+ return accum;
20
+ }, [])
21
+ .sort((a, b) => a.timestamp - b.timestamp);
22
+ const sortedProducerData = Object.keys(producerData)
23
+ .reduce((accum, key) => {
24
+ const identifier = Number(key);
25
+ const entries = producerData[identifier] ?? [];
26
+ accum.push(...entries.map((entry) => parseData(entry)));
27
+ return accum;
28
+ }, [])
29
+ .sort((a, b) => a.timestamp - b.timestamp);
30
+ if (sortedProducerData.length !== sortedConsumerData.length) {
31
+ throw new Error("Producer data and consumer data does not match in length");
32
+ }
33
+ let counter = -1;
34
+ const isMatching = sortedProducerData.every((producer, index) => {
35
+ counter = index;
36
+ const consumer = sortedConsumerData[index];
37
+ return (producer.child === consumer.child && producer.action === consumer.action);
38
+ });
39
+ if (!isMatching) {
40
+ const errorLines = [
41
+ `Producer data and consumer data do not sort the same way as of record ${counter}:`,
42
+ " | CONSUMER | PRODUCER |",
43
+ " | id | action | timestamp | id | action | timestamp |",
44
+ ];
45
+ sortedProducerData.forEach((producer, index) => {
46
+ if (index < counter || index > counter + 15) {
47
+ return;
48
+ }
49
+ const consumer = sortedConsumerData[index];
50
+ errorLines.push(` ${index < 10 ? `0${index}` : index}| ${consumer.child} | ${consumer.action} | ${consumer.timestamp} | ${producer.child} | ${producer.action} | ${producer.timestamp} |`);
51
+ });
52
+ throw new Error(errorLines.join("\n"));
53
+ }
54
+ return {
55
+ consumer: sortedConsumerData,
56
+ producer: sortedProducerData,
57
+ };
58
+ };
59
+ const formatTimestamp = (value) => new Date(value).toISOString();
60
+ export const reportingComparer = async (consumerData, producerData, options) => {
61
+ const reporter = options?.reporter ??
62
+ new TestReporter(options?.testCase ?? "consumer-producer");
63
+ const referencePrefix = options?.referencePrefix ?? "consumer-producer";
64
+ try {
65
+ const comparison = await defaultComparer(consumerData, producerData);
66
+ const rows = comparison.consumer.map((consumerEntry, index) => {
67
+ const producerEntry = comparison.producer[index];
68
+ return {
69
+ Index: `${index}`,
70
+ "Consumer Child": consumerEntry.child,
71
+ "Consumer Action": consumerEntry.action,
72
+ "Consumer Timestamp": formatTimestamp(consumerEntry.timestamp),
73
+ "Producer Child": producerEntry?.child ?? "N/A",
74
+ "Producer Action": producerEntry?.action ?? "N/A",
75
+ "Producer Timestamp": producerEntry
76
+ ? formatTimestamp(producerEntry.timestamp)
77
+ : "N/A",
78
+ };
79
+ });
80
+ await Promise.allSettled([
81
+ reporter.reportMessage(`${referencePrefix}-comparison`, `Consumer and producer logs matched (${comparison.consumer.length} entries).`),
82
+ reporter.reportTable(`${referencePrefix}-logs`, {
83
+ headers: [
84
+ "Index",
85
+ "Consumer Child",
86
+ "Consumer Action",
87
+ "Consumer Timestamp",
88
+ "Producer Child",
89
+ "Producer Action",
90
+ "Producer Timestamp",
91
+ ],
92
+ rows,
93
+ }),
94
+ ]);
95
+ return comparison;
96
+ }
97
+ catch (error) {
98
+ const message = error instanceof Error ? error.message : String(error ?? "Unknown error");
99
+ await Promise.allSettled([
100
+ reporter.reportMessage(`${referencePrefix}-mismatch`, message),
101
+ reporter.reportObject(`${referencePrefix}-consumer`, consumerData),
102
+ reporter.reportObject(`${referencePrefix}-producer`, producerData),
103
+ ]);
104
+ throw error;
105
+ }
106
+ };
107
+ export class ConsumerRunner extends LoggedClass {
108
+ constructor(action, consumerHandler, compareHandler) {
109
+ super();
110
+ this.forkedCache = [];
111
+ this.consumerResults = {};
112
+ this.producerResults = {};
113
+ this.childExitPromises = [];
114
+ this.completionTriggered = false;
115
+ this.activeHandlers = 0;
116
+ this.action = action;
117
+ this.handler = consumerHandler;
118
+ this.comparerHandle = compareHandler ?? defaultComparer;
119
+ this.reset();
120
+ }
121
+ reset() {
122
+ this.forkedCache = [];
123
+ this.consumerResults = {};
124
+ this.producerResults = {};
125
+ this.completionTriggered = false;
126
+ this.childExitPromises = [];
127
+ this.activeHandlers = 0;
128
+ }
129
+ waitForChildExit() {
130
+ if (!this.childExitPromises?.length) {
131
+ return Promise.resolve();
132
+ }
133
+ const exits = [...this.childExitPromises];
134
+ this.childExitPromises = [];
135
+ return Promise.allSettled(exits).then(() => void 0);
136
+ }
137
+ store(identifier, action, timeout, times, count, random) {
138
+ const logParts = [
139
+ Date.now(),
140
+ "PRODUCER",
141
+ identifier,
142
+ action,
143
+ ];
144
+ if (timeout) {
145
+ logParts.push(timeout);
146
+ }
147
+ if (times && count) {
148
+ logParts.push(`${count}/${times}`, random ?? false);
149
+ }
150
+ const log = logParts.join(" - ");
151
+ if (!this.producerResults[identifier]) {
152
+ this.producerResults[identifier] = [];
153
+ }
154
+ this.producerResults[identifier].push(log);
155
+ }
156
+ recordConsumer(identifier) {
157
+ const logParts = [
158
+ Date.now(),
159
+ "CONSUMER",
160
+ identifier,
161
+ this.action,
162
+ ];
163
+ const log = logParts.join(" - ");
164
+ if (!this.consumerResults[identifier]) {
165
+ this.consumerResults[identifier] = [];
166
+ }
167
+ this.consumerResults[identifier].push(log);
168
+ }
169
+ isProducerComplete(count, times) {
170
+ const producerKeys = Object.keys(this.producerResults);
171
+ if (producerKeys.length !== count) {
172
+ return false;
173
+ }
174
+ return producerKeys.every((key) => this.producerResults[Number(key)]?.length === times);
175
+ }
176
+ isConsumerComplete(count, times) {
177
+ const consumerKeys = Object.keys(this.consumerResults);
178
+ if (consumerKeys.length !== count) {
179
+ return false;
180
+ }
181
+ return consumerKeys.every((key) => this.consumerResults[Number(key)]?.length === times);
182
+ }
183
+ terminateChildren(forceKill = false) {
184
+ if (!this.forkedCache) {
185
+ return this.waitForChildExit();
186
+ }
187
+ const cached = this.forkedCache;
188
+ this.forkedCache = undefined;
189
+ cached.forEach((forked, index) => {
190
+ if (!forked.connected && !forceKill) {
191
+ return;
192
+ }
193
+ try {
194
+ forked.send({
195
+ identifier: index,
196
+ terminate: true,
197
+ });
198
+ }
199
+ catch {
200
+ // IPC channel already closed; nothing else to do.
201
+ }
202
+ if (forceKill && !forked.killed) {
203
+ forked.kill();
204
+ }
205
+ });
206
+ return this.waitForChildExit();
207
+ }
208
+ async run(count, timeout, times, random) {
209
+ this.reset();
210
+ const childPath = join(__dirname, "ProducerChildProcess.cjs");
211
+ return new Promise((resolve, reject) => {
212
+ const snapshotState = () => {
213
+ const summarize = (records) => Object.keys(records).reduce((acc, key) => {
214
+ acc[key] = records[Number(key)]?.length ?? 0;
215
+ return acc;
216
+ }, {});
217
+ return {
218
+ producers: summarize(this.producerResults),
219
+ consumers: summarize(this.consumerResults),
220
+ activeHandlers: this.activeHandlers,
221
+ };
222
+ };
223
+ const handleError = (error) => {
224
+ if (this.completionTriggered) {
225
+ return;
226
+ }
227
+ this.completionTriggered = true;
228
+ Promise.resolve(this.terminateChildren(true)).finally(() => reject(error));
229
+ };
230
+ const finalizeIfComplete = () => {
231
+ if (this.completionTriggered) {
232
+ return;
233
+ }
234
+ if (!this.isProducerComplete(count, times) ||
235
+ !this.isConsumerComplete(count, times) ||
236
+ this.activeHandlers > 0) {
237
+ return;
238
+ }
239
+ this.completionTriggered = true;
240
+ if (process.env.DEBUG_CONSUMER_RUNNER === "1") {
241
+ console.debug("ConsumerRunner finalize state", snapshotState());
242
+ }
243
+ try {
244
+ const comparisonPromise = Promise.resolve(this.comparerHandle(this.consumerResults, this.producerResults));
245
+ Promise.all([comparisonPromise, this.waitForChildExit()])
246
+ .then(async ([comparison]) => {
247
+ await new Promise((resolveDelay) => setImmediate(resolveDelay));
248
+ resolve(comparison);
249
+ })
250
+ .catch(reject);
251
+ }
252
+ catch (error) {
253
+ reject(error);
254
+ }
255
+ };
256
+ for (let identifier = 1; identifier < count + 1; identifier += 1) {
257
+ const forked = fork(childPath);
258
+ this.forkedCache?.push(forked);
259
+ this.childExitPromises?.push(new Promise((resolveChild) => {
260
+ forked.once("exit", () => resolveChild());
261
+ }));
262
+ forked.on("error", handleError);
263
+ forked.on("message", async (message) => {
264
+ if (this.completionTriggered) {
265
+ return;
266
+ }
267
+ const { identifier: childId, args, action, timeout: childTimeout, times: childTimes, random: childRandom, } = message;
268
+ this.activeHandlers += 1;
269
+ let handlerFailed = false;
270
+ if (process.env.DEBUG_CONSUMER_RUNNER === "1") {
271
+ console.debug("ConsumerRunner message:start", {
272
+ childId,
273
+ producerCount: this.producerResults[childId]?.length ?? 0,
274
+ consumerCount: this.consumerResults[childId]?.length ?? 0,
275
+ activeHandlers: this.activeHandlers,
276
+ });
277
+ }
278
+ try {
279
+ this.store(childId, action, childTimeout, childTimes, count, childRandom);
280
+ const handlerArgs = Array.isArray(args) ? args : [];
281
+ await Promise.resolve(this.handler(childId, ...handlerArgs));
282
+ this.recordConsumer(childId);
283
+ if (process.env.DEBUG_CONSUMER_RUNNER === "1") {
284
+ console.debug("ConsumerRunner message:complete", {
285
+ childId,
286
+ producerCount: this.producerResults[childId]?.length ?? 0,
287
+ consumerCount: this.consumerResults[childId]?.length ?? 0,
288
+ activeHandlers: this.activeHandlers,
289
+ });
290
+ }
291
+ }
292
+ catch (error) {
293
+ handlerFailed = true;
294
+ handleError(error);
295
+ }
296
+ finally {
297
+ this.activeHandlers = Math.max(0, this.activeHandlers - 1);
298
+ if (!handlerFailed) {
299
+ finalizeIfComplete();
300
+ }
301
+ }
302
+ });
303
+ }
304
+ this.forkedCache?.forEach((forked, index) => {
305
+ forked.send({
306
+ identifier: index,
307
+ action: this.action,
308
+ timeout,
309
+ times,
310
+ random,
311
+ });
312
+ });
313
+ });
314
+ }
315
+ }
316
+ //# sourceMappingURL=Consumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Consumer.js","sourceRoot":"","sources":["../../../src/tests/Consumer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ type ParentMessage = {
2
+ identifier: number;
3
+ action: string;
4
+ timeout?: number;
5
+ times: number;
6
+ random?: boolean;
7
+ terminate?: boolean;
8
+ };
9
+ type ProducerResponse = {
10
+ identifier: number;
11
+ action: string;
12
+ timeout?: number;
13
+ times: number;
14
+ random?: boolean;
15
+ result?: string[];
16
+ };
17
+ declare let shuttingDown: boolean;
18
+ declare const completeAndExit: (logMessage?: string) => void;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ let shuttingDown = false;
3
+ const completeAndExit = (logMessage) => {
4
+ if (shuttingDown) {
5
+ return;
6
+ }
7
+ shuttingDown = true;
8
+ if (logMessage) {
9
+ console.log(logMessage);
10
+ }
11
+ setImmediate(() => process.exit(0));
12
+ };
13
+ process.on("message", (args) => {
14
+ const result = [];
15
+ const { identifier, action, timeout, times, random, terminate } = args;
16
+ const tick = (count) => {
17
+ const logParts = [Date.now(), 'PRODUCER', identifier, action];
18
+ if (timeout) {
19
+ logParts.push(timeout);
20
+ }
21
+ if (times && count) {
22
+ logParts.push(`${count}/${times}`, random ?? false);
23
+ }
24
+ const log = logParts.join(' - ');
25
+ result.push(log);
26
+ const response = { identifier, action, timeout, times, random };
27
+ if (result.length === times) {
28
+ response.result = [...result];
29
+ }
30
+ process.send?.(response);
31
+ if (response.result) {
32
+ completeAndExit();
33
+ }
34
+ else if (!times) {
35
+ completeAndExit();
36
+ }
37
+ };
38
+ if (terminate) {
39
+ const log = [Date.now(), "PRODUCER", identifier, action, "Quitting!"].join(" - ");
40
+ completeAndExit(log);
41
+ return;
42
+ }
43
+ if (!timeout) {
44
+ tick(times);
45
+ return;
46
+ }
47
+ const getTimeout = () => {
48
+ if (!random) {
49
+ return timeout;
50
+ }
51
+ return Math.floor(Math.random() * timeout);
52
+ };
53
+ let actionCount = 0;
54
+ const iterator = () => {
55
+ const currentTimeout = getTimeout();
56
+ setTimeout(() => {
57
+ actionCount += 1;
58
+ tick(actionCount);
59
+ if (actionCount < times) {
60
+ iterator();
61
+ }
62
+ }, currentTimeout);
63
+ };
64
+ iterator();
65
+ });
66
+ //# sourceMappingURL=ProducerChildProcess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProducerChildProcess.js","sourceRoot":"","sources":["../../../src/tests/ProducerChildProcess.ts"],"names":[],"mappings":"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"}