@code-pushup/utils 0.110.0 → 0.111.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.
@@ -1 +1 @@
1
- {"version":3,"file":"performance-observer.js","sourceRoot":"","sources":["../../../src/lib/performance-observer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"performance-observer.js","sourceRoot":"","sources":["../../../src/lib/performance-observer.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,24 @@
1
+ /**
2
+ * Environment variable name for enabling/disabling profiling globally.
3
+ * When set to 'true', profiling is enabled. When set to 'false' or unset, profiling is disabled.
4
+ *
5
+ * @example
6
+ * CP_PROFILING=true npm run dev
7
+ */
1
8
  export declare const PROFILER_ENABLED_ENV_VAR = "CP_PROFILING";
2
- export declare const PROFILER_COORDINATOR_FLAG_ENV_VAR = "CP_PROFILER_COORDINATOR";
3
- export declare const PROFILER_ORIGIN_PID_ENV_VAR = "CP_PROFILER_ORIGIN_PID";
4
- export declare const PROFILER_DIRECTORY_ENV_VAR = "CP_PROFILER_DIR";
5
- export declare const PROFILER_BASE_NAME = "trace";
6
- export declare const PROFILER_DIRECTORY = "./tmp/profiles";
9
+ /**
10
+ * Environment variable name for enabling debug mode for profiler state transitions.
11
+ * When set to 'true', profiler state transitions create performance marks for debugging.
12
+ *
13
+ * @example
14
+ * CP_PROFILER_DEBUG=true npm run dev
15
+ */
16
+ export declare const PROFILER_DEBUG_ENV_VAR = "CP_PROFILER_DEBUG";
17
+ /**
18
+ * Environment variable name for setting the Sharded WAL Coordinator ID.
19
+ * This ID is used to identify the coordinator instance in a sharded Write-Ahead Logging setup.
20
+ *
21
+ * @example
22
+ * CP_SHARDED_WAL_COORDINATOR_ID=coordinator-1 npm run dev
23
+ */
24
+ export declare const SHARDED_WAL_COORDINATOR_ID_ENV_VAR = "CP_SHARDED_WAL_COORDINATOR_ID";
@@ -1,7 +1,25 @@
1
+ /**
2
+ * Environment variable name for enabling/disabling profiling globally.
3
+ * When set to 'true', profiling is enabled. When set to 'false' or unset, profiling is disabled.
4
+ *
5
+ * @example
6
+ * CP_PROFILING=true npm run dev
7
+ */
1
8
  export const PROFILER_ENABLED_ENV_VAR = 'CP_PROFILING';
2
- export const PROFILER_COORDINATOR_FLAG_ENV_VAR = 'CP_PROFILER_COORDINATOR';
3
- export const PROFILER_ORIGIN_PID_ENV_VAR = 'CP_PROFILER_ORIGIN_PID';
4
- export const PROFILER_DIRECTORY_ENV_VAR = 'CP_PROFILER_DIR';
5
- export const PROFILER_BASE_NAME = 'trace';
6
- export const PROFILER_DIRECTORY = './tmp/profiles';
9
+ /**
10
+ * Environment variable name for enabling debug mode for profiler state transitions.
11
+ * When set to 'true', profiler state transitions create performance marks for debugging.
12
+ *
13
+ * @example
14
+ * CP_PROFILER_DEBUG=true npm run dev
15
+ */
16
+ export const PROFILER_DEBUG_ENV_VAR = 'CP_PROFILER_DEBUG';
17
+ /**
18
+ * Environment variable name for setting the Sharded WAL Coordinator ID.
19
+ * This ID is used to identify the coordinator instance in a sharded Write-Ahead Logging setup.
20
+ *
21
+ * @example
22
+ * CP_SHARDED_WAL_COORDINATOR_ID=coordinator-1 npm run dev
23
+ */
24
+ export const SHARDED_WAL_COORDINATOR_ID_ENV_VAR = 'CP_SHARDED_WAL_COORDINATOR_ID';
7
25
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/lib/profiler/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CAAC;AACvD,MAAM,CAAC,MAAM,iCAAiC,GAAG,yBAAyB,CAAC;AAC3E,MAAM,CAAC,MAAM,2BAA2B,GAAG,wBAAwB,CAAC;AACpE,MAAM,CAAC,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAC1C,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/lib/profiler/constants.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAC7C,+BAA+B,CAAC"}
@@ -0,0 +1,101 @@
1
+ import { type PerformanceObserverOptions } from '../performance-observer.js';
2
+ import type { ActionTrackEntryPayload } from '../user-timing-extensibility-api.type.js';
3
+ import { Profiler, type ProfilerOptions } from './profiler.js';
4
+ /**
5
+ * Options for configuring a NodejsProfiler instance.
6
+ *
7
+ * Extends ProfilerOptions with a required sink parameter.
8
+ *
9
+ * @template Tracks - Record type defining available track names and their configurations
10
+ */
11
+ export type NodejsProfilerOptions<DomainEvents extends string | object, Tracks extends Record<string, ActionTrackEntryPayload>> = ProfilerOptions<Tracks> & Omit<PerformanceObserverOptions<DomainEvents>, 'sink'> & {
12
+ /**
13
+ * File path for the WriteAheadLogFile sink.
14
+ * If not provided, defaults to `trace.json` in the current working directory.
15
+ *
16
+ * @default path.join(process.cwd(), 'trace.json')
17
+ */
18
+ filename?: string;
19
+ /**
20
+ * Name of the environment variable to check for debug mode.
21
+ * When the env var is set to 'true', profiler state transitions create performance marks for debugging.
22
+ *
23
+ * @default 'CP_PROFILER_DEBUG'
24
+ */
25
+ debugEnvVar?: string;
26
+ };
27
+ /**
28
+ * Performance profiler with automatic process exit handling for buffered performance data.
29
+ *
30
+ * This class extends the base {@link Profiler} with automatic flushing of performance data
31
+ * when the process exits. It automatically creates a {@link WriteAheadLogFile} sink that buffers
32
+ * performance entries and ensures they are written out during process termination, even for unexpected exits.
33
+ *
34
+ * The sink uses a default codec for serializing performance data to JSON format,
35
+ * enabling compatibility with Chrome DevTools trace file format.
36
+ *
37
+ * The profiler automatically subscribes to the performance observer when enabled and installs
38
+ * exit handlers that flush buffered data on process termination (signals, fatal errors, or normal exit).
39
+ *
40
+ * @template DomainEvents - The type of domain-specific events encoded by the performance observer sink
41
+ * @template Tracks - Record type defining available track names and their configurations
42
+ */
43
+ export declare class NodejsProfiler<DomainEvents extends string | object, Tracks extends Record<string, ActionTrackEntryPayload> = Record<string, ActionTrackEntryPayload>> extends Profiler<Tracks> {
44
+ #private;
45
+ /**
46
+ * Creates a NodejsProfiler instance.
47
+ * A WriteAheadLogFile sink is automatically created for buffering performance data.
48
+ * @param options - Configuration options
49
+ */
50
+ constructor(options: NodejsProfilerOptions<DomainEvents, Tracks>);
51
+ /**
52
+ * Returns whether debug mode is enabled for profiler state transitions.
53
+ *
54
+ * Debug mode is initially determined by the environment variable specified by `debugEnvVar`
55
+ * (defaults to 'CP_PROFILER_DEBUG') during construction, but can be changed at runtime
56
+ * using {@link setDebugMode}. When enabled, profiler state transitions create
57
+ * performance marks for debugging.
58
+ *
59
+ * @returns true if debug mode is enabled, false otherwise
60
+ */
61
+ get debug(): boolean;
62
+ /**
63
+ * Sets debug mode for profiler state transitions.
64
+ *
65
+ * When debug mode is enabled, profiler state transitions create performance marks
66
+ * for debugging. This allows runtime control of debug mode without needing to
67
+ * restart the application or change environment variables.
68
+ *
69
+ * @param enabled - Whether to enable debug mode
70
+ */
71
+ setDebugMode(enabled: boolean): void;
72
+ /**
73
+ * Closes profiler and releases resources. Idempotent, safe for exit handlers.
74
+ * **Exit Handler Usage**: Call only this method from process exit handlers.
75
+ */
76
+ close(): void;
77
+ /** @returns Current profiler state */
78
+ get state(): 'idle' | 'running' | 'closed';
79
+ /** @returns Whether profiler is in 'running' state */
80
+ isEnabled(): boolean;
81
+ /** Enables profiling (start/stop) */
82
+ setEnabled(enabled: boolean): void;
83
+ /** @returns Queue statistics and profiling state for monitoring */
84
+ get stats(): {
85
+ debug: boolean;
86
+ state: "idle" | "running" | "closed";
87
+ walOpen: boolean;
88
+ isSubscribed: boolean;
89
+ queued: number;
90
+ dropped: number;
91
+ written: number;
92
+ maxQueueSize: number;
93
+ flushThreshold: number;
94
+ addedSinceLastFlush: number;
95
+ buffered: boolean;
96
+ };
97
+ /** Flushes buffered performance data to sink. */
98
+ flush(): void;
99
+ /** @returns The file path of the WriteAheadLogFile sink */
100
+ get filePath(): string;
101
+ }
@@ -0,0 +1,217 @@
1
+ import path from 'node:path';
2
+ import { isEnvVarEnabled } from '../env.js';
3
+ import { subscribeProcessExit } from '../exit-process.js';
4
+ import { PerformanceObserverSink, } from '../performance-observer.js';
5
+ import { objectToEntries } from '../transform.js';
6
+ import { errorToMarkerPayload } from '../user-timing-extensibility-api-utils.js';
7
+ import { WriteAheadLogFile, getShardId, getShardedGroupId, getShardedPath, } from '../wal.js';
8
+ import { PROFILER_DEBUG_ENV_VAR, PROFILER_ENABLED_ENV_VAR, } from './constants.js';
9
+ import { Profiler } from './profiler.js';
10
+ import { traceEventWalFormat } from './wal-json-trace.js';
11
+ /**
12
+ * Performance profiler with automatic process exit handling for buffered performance data.
13
+ *
14
+ * This class extends the base {@link Profiler} with automatic flushing of performance data
15
+ * when the process exits. It automatically creates a {@link WriteAheadLogFile} sink that buffers
16
+ * performance entries and ensures they are written out during process termination, even for unexpected exits.
17
+ *
18
+ * The sink uses a default codec for serializing performance data to JSON format,
19
+ * enabling compatibility with Chrome DevTools trace file format.
20
+ *
21
+ * The profiler automatically subscribes to the performance observer when enabled and installs
22
+ * exit handlers that flush buffered data on process termination (signals, fatal errors, or normal exit).
23
+ *
24
+ * @template DomainEvents - The type of domain-specific events encoded by the performance observer sink
25
+ * @template Tracks - Record type defining available track names and their configurations
26
+ */
27
+ export class NodejsProfiler extends Profiler {
28
+ #sink;
29
+ #performanceObserverSink;
30
+ #state = 'idle';
31
+ #debug;
32
+ #unsubscribeExitHandlers;
33
+ /**
34
+ * Creates a NodejsProfiler instance.
35
+ * A WriteAheadLogFile sink is automatically created for buffering performance data.
36
+ * @param options - Configuration options
37
+ */
38
+ // eslint-disable-next-line max-lines-per-function
39
+ constructor(options) {
40
+ const { encodePerfEntry, captureBufferedEntries, flushThreshold, maxQueueSize, enabled, filename, debugEnvVar = PROFILER_DEBUG_ENV_VAR, ...profilerOptions } = options;
41
+ const initialEnabled = enabled ?? isEnvVarEnabled(PROFILER_ENABLED_ENV_VAR);
42
+ super({ ...profilerOptions, enabled: initialEnabled });
43
+ const walFormat = traceEventWalFormat();
44
+ this.#sink = new WriteAheadLogFile({
45
+ file: filename ??
46
+ path.join(process.cwd(), getShardedPath({
47
+ dir: 'tmp/profiles',
48
+ groupId: getShardedGroupId(),
49
+ shardId: getShardId(),
50
+ format: walFormat,
51
+ })),
52
+ codec: walFormat.codec,
53
+ });
54
+ this.#debug = isEnvVarEnabled(debugEnvVar);
55
+ this.#performanceObserverSink = new PerformanceObserverSink({
56
+ sink: this.#sink,
57
+ encodePerfEntry,
58
+ captureBufferedEntries,
59
+ flushThreshold,
60
+ maxQueueSize,
61
+ debugEnvVar,
62
+ });
63
+ this.#unsubscribeExitHandlers = subscribeProcessExit({
64
+ onError: (error, kind) => {
65
+ this.#handleFatalError(error, kind);
66
+ },
67
+ onExit: (_code) => {
68
+ this.close();
69
+ },
70
+ });
71
+ if (initialEnabled) {
72
+ this.#transition('running');
73
+ }
74
+ }
75
+ /**
76
+ * Returns whether debug mode is enabled for profiler state transitions.
77
+ *
78
+ * Debug mode is initially determined by the environment variable specified by `debugEnvVar`
79
+ * (defaults to 'CP_PROFILER_DEBUG') during construction, but can be changed at runtime
80
+ * using {@link setDebugMode}. When enabled, profiler state transitions create
81
+ * performance marks for debugging.
82
+ *
83
+ * @returns true if debug mode is enabled, false otherwise
84
+ */
85
+ get debug() {
86
+ return this.#debug;
87
+ }
88
+ /**
89
+ * Sets debug mode for profiler state transitions.
90
+ *
91
+ * When debug mode is enabled, profiler state transitions create performance marks
92
+ * for debugging. This allows runtime control of debug mode without needing to
93
+ * restart the application or change environment variables.
94
+ *
95
+ * @param enabled - Whether to enable debug mode
96
+ */
97
+ setDebugMode(enabled) {
98
+ this.#debug = enabled;
99
+ }
100
+ /**
101
+ * Creates a performance marker for a profiler state transition.
102
+ * @param transition - The state transition that occurred
103
+ */
104
+ #transitionMarker(transition) {
105
+ const transitionMarkerPayload = {
106
+ dataType: 'marker',
107
+ color: 'primary',
108
+ tooltipText: `Profiler state transition: ${transition}`,
109
+ properties: [['Transition', transition], ...objectToEntries(this.stats)],
110
+ };
111
+ this.marker(transition, transitionMarkerPayload);
112
+ }
113
+ /**
114
+ * Handles fatal errors by marking them and shutting down the profiler.
115
+ * @param error - The error that occurred
116
+ * @param kind - The kind of fatal error (uncaughtException or unhandledRejection)
117
+ */
118
+ #handleFatalError(error, kind) {
119
+ this.marker('Fatal Error', errorToMarkerPayload(error, {
120
+ tooltipText: `${kind} caused fatal error`,
121
+ }));
122
+ this.close(); // Ensures buffers flush and sink finalizes
123
+ }
124
+ /**
125
+ * Transitions the profiler to a new state, performing necessary setup/teardown operations.
126
+ *
127
+ * State transitions enforce lifecycle invariants:
128
+ * - `idle -> running`: Enables profiling, opens sink, and subscribes to performance observer
129
+ * - `running -> idle`: Disables profiling, unsubscribes, and closes sink (sink will be reopened on re-enable)
130
+ * - `running -> closed`: Disables profiling, unsubscribes, and closes sink (irreversible)
131
+ * - `idle -> closed`: Closes sink if it was opened (irreversible)
132
+ *
133
+ * @param next - The target state to transition to
134
+ * @throws {Error} If attempting to transition from 'closed' state or invalid transition
135
+ */
136
+ #transition(next) {
137
+ if (this.#state === next) {
138
+ return;
139
+ }
140
+ if (this.#state === 'closed') {
141
+ throw new Error('Profiler already closed');
142
+ }
143
+ const transition = `${this.#state}->${next}`;
144
+ switch (transition) {
145
+ case 'idle->running':
146
+ super.setEnabled(true);
147
+ this.#sink.open?.();
148
+ this.#performanceObserverSink.subscribe();
149
+ break;
150
+ case 'running->idle':
151
+ case 'running->closed':
152
+ super.setEnabled(false);
153
+ this.#performanceObserverSink.unsubscribe();
154
+ this.#sink.close?.();
155
+ break;
156
+ case 'idle->closed':
157
+ // Sink may have been opened before, close it
158
+ this.#sink.close?.();
159
+ break;
160
+ default:
161
+ throw new Error(`Invalid transition: ${this.#state} -> ${next}`);
162
+ }
163
+ this.#state = next;
164
+ if (this.#debug) {
165
+ this.#transitionMarker(transition);
166
+ }
167
+ }
168
+ /**
169
+ * Closes profiler and releases resources. Idempotent, safe for exit handlers.
170
+ * **Exit Handler Usage**: Call only this method from process exit handlers.
171
+ */
172
+ close() {
173
+ if (this.#state === 'closed') {
174
+ return;
175
+ }
176
+ this.#unsubscribeExitHandlers?.();
177
+ this.#transition('closed');
178
+ }
179
+ /** @returns Current profiler state */
180
+ get state() {
181
+ return this.#state;
182
+ }
183
+ /** @returns Whether profiler is in 'running' state */
184
+ isEnabled() {
185
+ return this.#state === 'running';
186
+ }
187
+ /** Enables profiling (start/stop) */
188
+ setEnabled(enabled) {
189
+ if (enabled) {
190
+ this.#transition('running');
191
+ }
192
+ else {
193
+ this.#transition('idle');
194
+ }
195
+ }
196
+ /** @returns Queue statistics and profiling state for monitoring */
197
+ get stats() {
198
+ return {
199
+ ...this.#performanceObserverSink.getStats(),
200
+ debug: this.#debug,
201
+ state: this.#state,
202
+ walOpen: !this.#sink.isClosed(),
203
+ };
204
+ }
205
+ /** Flushes buffered performance data to sink. */
206
+ flush() {
207
+ if (this.#state === 'closed') {
208
+ return; // No-op if closed
209
+ }
210
+ this.#performanceObserverSink.flush();
211
+ }
212
+ /** @returns The file path of the WriteAheadLogFile sink */
213
+ get filePath() {
214
+ return this.#sink.getPath();
215
+ }
216
+ }
217
+ //# sourceMappingURL=profiler-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiler-node.js","sourceRoot":"","sources":["../../../../src/lib/profiler/profiler-node.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { performance } from 'node:perf_hooks';
1
2
  import process from 'node:process';
2
3
  import { threadId } from 'node:worker_threads';
3
4
  import { isEnvVarEnabled } from '../env.js';
@@ -20,7 +21,7 @@ export function getProfilerId() {
20
21
  export class Profiler {
21
22
  static instanceCount = 0;
22
23
  id = getProfilerId();
23
- #enabled;
24
+ #enabled = false;
24
25
  #defaults;
25
26
  tracks;
26
27
  #ctxOf;
@@ -96,7 +97,7 @@ export class Profiler {
96
97
  * });
97
98
  */
98
99
  marker(name, opt) {
99
- if (!this.#enabled) {
100
+ if (!this.isEnabled()) {
100
101
  return;
101
102
  }
102
103
  performance.mark(name, asOptions(markerPayload({
@@ -122,7 +123,7 @@ export class Profiler {
122
123
  *
123
124
  */
124
125
  measure(event, work, options) {
125
- if (!this.#enabled) {
126
+ if (!this.isEnabled()) {
126
127
  return work();
127
128
  }
128
129
  const { start, success, error } = this.#ctxOf(event, options);
@@ -154,7 +155,7 @@ export class Profiler {
154
155
  *
155
156
  */
156
157
  async measureAsync(event, work, options) {
157
- if (!this.#enabled) {
158
+ if (!this.isEnabled()) {
158
159
  return await work();
159
160
  }
160
161
  const { start, success, error } = this.#ctxOf(event, options);
@@ -1 +1 @@
1
- {"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../../../src/lib/profiler/profiler.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAIL,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,GACZ,MAAM,2CAA2C,CAAC;AAMnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,qDAAqD;IACrD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,QAAQ,IAAI,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC;AACxG,CAAC;AAqCD;;;;;;GAMG;AACH,MAAM,OAAO,QAAQ;IACnB,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC;IAChB,EAAE,GAAG,aAAa,EAAE,CAAC;IAC9B,QAAQ,CAAU;IACT,SAAS,CAA0B;IACnC,MAAM,CAAuD;IAC7D,MAAM,CAAgC;IAE/C;;;;;;;;;;;OAWG;IACH,YAAY,OAA2B;QACrC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC;QACzD,MAAM,QAAQ,GAAG,aAAa,CAAC;QAE/B,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,eAAe,CAAC,wBAAwB,CAAC,CAAC;QACrE,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,CAAC;QAC3C,IAAI,CAAC,MAAM,GAAG,MAAM;YAClB,CAAC,CAAC,WAAW,CAAC,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC;YAChD,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;YACvB,GAAG,QAAQ;YACX,QAAQ;YACR,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,OAAgB;QACzB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC;QACrD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,IAAY,EAAE,GAAmB;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QAED,WAAW,CAAC,IAAI,CACd,IAAI,EACJ,SAAS,CACP,aAAa,CAAC;YACZ,gDAAgD;YAChD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,GAAG,GAAG;SACP,CAAC,CACH,CACF,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAI,KAAa,EAAE,IAAa,EAAE,OAA2B;QAClE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC9D,KAAK,EAAE,CAAC;QACR,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,CAAC,CAAC,CAAC;YACX,OAAO,CAAC,CAAC;QACX,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,KAAK,CAAC,MAAM,CAAC,CAAC;YACd,MAAM,MAAM,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,YAAY,CAChB,KAAa,EACb,IAAsB,EACtB,OAA2B;QAE3B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,MAAM,IAAI,EAAE,CAAC;QACtB,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC9D,KAAK,EAAE,CAAC;QACR,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,CAAC,CAAC,CAAC;YACX,OAAO,CAAC,CAAC;QACX,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,KAAK,CAAC,MAAM,CAAC,CAAC;YACd,MAAM,MAAM,CAAC;QACf,CAAC;IACH,CAAC"}
1
+ {"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../../../src/lib/profiler/profiler.ts"],"names":[],"mappings":"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"}
package/src/lib/wal.d.ts CHANGED
@@ -16,8 +16,20 @@ export type InvalidEntry<O = string> = {
16
16
  * Interface for sinks that can append items.
17
17
  * Allows for different types of appendable storage (WAL, in-memory, etc.)
18
18
  */
19
- export type AppendableSink<T> = {
19
+ export type AppendableSink<T> = Recoverable & {
20
20
  append: (item: T) => void;
21
+ isClosed: () => boolean;
22
+ open?: () => void;
23
+ close?: () => void;
24
+ };
25
+ /**
26
+ * Interface for sinks that support recovery operations.
27
+ * Represents the recoverable subset of AppendableSink functionality.
28
+ */
29
+ export type Recoverable = {
30
+ recover: () => RecoverResult<unknown>;
31
+ repack: (out?: string) => void;
32
+ finalize?: (opt?: Record<string, unknown>) => void;
21
33
  };
22
34
  /**
23
35
  * Result of recovering records from a WAL file.
@@ -149,13 +161,13 @@ export declare function parseWalFormat<T extends object | string = object>(forma
149
161
  *
150
162
  * @returns true if this is the leader WAL process, false otherwise
151
163
  */
152
- export declare function isLeaderWal(envVarName: string, profilerID: string): boolean;
164
+ export declare function isCoordinatorProcess(envVarName: string, profilerID: string): boolean;
153
165
  /**
154
166
  * Initialize the origin PID environment variable if not already set.
155
167
  * This must be done as early as possible before any user code runs.
156
168
  * Sets envVarName to the current process ID if not already defined.
157
169
  */
158
- export declare function setLeaderWal(envVarName: string, profilerID: string): void;
170
+ export declare function setCoordinatorProcess(envVarName: string, profilerID: string): void;
159
171
  /**
160
172
  * Generates a human-readable shard ID.
161
173
  * This ID is unique per process/thread/shard combination and used in the file name.
@@ -214,15 +226,31 @@ export declare function getShardedFinalPath<T extends object | string = object>(
214
226
  */
215
227
  export declare class ShardedWal<T extends object | string = object> {
216
228
  #private;
229
+ static instanceCount: number;
217
230
  readonly groupId: string;
218
231
  /**
219
232
  * Create a sharded WAL manager.
233
+ *
234
+ * @param opt.dir - Base directory to store shard files (defaults to process.cwd())
235
+ * @param opt.format - WAL format configuration
236
+ * @param opt.groupId - Group ID for sharding (defaults to generated group ID)
237
+ * @param opt.coordinatorIdEnvVar - Environment variable name for storing coordinator ID (defaults to CP_SHARDED_WAL_COORDINATOR_ID)
220
238
  */
221
239
  constructor(opt: {
222
240
  dir?: string;
223
241
  format: Partial<WalFormat<T>>;
224
242
  groupId?: string;
243
+ coordinatorIdEnvVar: string;
225
244
  });
245
+ /**
246
+ * Is this instance the coordinator?
247
+ *
248
+ * Coordinator status is determined from the coordinatorIdEnvVar environment variable.
249
+ * The coordinator handles finalization and cleanup of shard files.
250
+ *
251
+ * @returns true if this instance is the coordinator, false otherwise
252
+ */
253
+ isCoordinator(): boolean;
226
254
  shard(shardId?: string): WriteAheadLogFile<T>;
227
255
  /** Get all shard file paths matching this WAL's base name */
228
256
  private shardFiles;
package/src/lib/wal.js CHANGED
@@ -216,7 +216,7 @@ export function parseWalFormat(format) {
216
216
  *
217
217
  * @returns true if this is the leader WAL process, false otherwise
218
218
  */
219
- export function isLeaderWal(envVarName, profilerID) {
219
+ export function isCoordinatorProcess(envVarName, profilerID) {
220
220
  return process.env[envVarName] === profilerID;
221
221
  }
222
222
  /**
@@ -224,7 +224,7 @@ export function isLeaderWal(envVarName, profilerID) {
224
224
  * This must be done as early as possible before any user code runs.
225
225
  * Sets envVarName to the current process ID if not already defined.
226
226
  */
227
- export function setLeaderWal(envVarName, profilerID) {
227
+ export function setCoordinatorProcess(envVarName, profilerID) {
228
228
  if (!process.env[envVarName]) {
229
229
  // eslint-disable-next-line functional/immutable-data
230
230
  process.env[envVarName] = profilerID;
@@ -232,6 +232,13 @@ export function setLeaderWal(envVarName, profilerID) {
232
232
  }
233
233
  // eslint-disable-next-line functional/no-let
234
234
  let shardCount = 0;
235
+ /**
236
+ * Generates a unique sharded WAL ID based on performance time origin, process ID, thread ID, and instance count.
237
+ */
238
+ function getShardedWalId() {
239
+ // eslint-disable-next-line functional/immutable-data
240
+ return `${Math.round(performance.timeOrigin)}.${process.pid}.${threadId}.${++ShardedWal.instanceCount}`;
241
+ }
235
242
  /**
236
243
  * Generates a human-readable shard ID.
237
244
  * This ID is unique per process/thread/shard combination and used in the file name.
@@ -316,19 +323,39 @@ export function getShardedFinalPath(opt) {
316
323
  * Handles distributed logging across multiple processes/files with atomic finalization.
317
324
  */
318
325
  export class ShardedWal {
326
+ static instanceCount = 0;
327
+ #id = getShardedWalId();
319
328
  groupId = getShardedGroupId();
320
329
  #format;
321
330
  #dir = process.cwd();
331
+ #isCoordinator;
322
332
  /**
323
333
  * Create a sharded WAL manager.
334
+ *
335
+ * @param opt.dir - Base directory to store shard files (defaults to process.cwd())
336
+ * @param opt.format - WAL format configuration
337
+ * @param opt.groupId - Group ID for sharding (defaults to generated group ID)
338
+ * @param opt.coordinatorIdEnvVar - Environment variable name for storing coordinator ID (defaults to CP_SHARDED_WAL_COORDINATOR_ID)
324
339
  */
325
340
  constructor(opt) {
326
- const { dir, format, groupId } = opt;
341
+ const { dir, format, groupId, coordinatorIdEnvVar } = opt;
327
342
  this.groupId = groupId ?? getShardedGroupId();
328
343
  if (dir) {
329
344
  this.#dir = dir;
330
345
  }
331
346
  this.#format = parseWalFormat(format);
347
+ this.#isCoordinator = isCoordinatorProcess(coordinatorIdEnvVar, this.#id);
348
+ }
349
+ /**
350
+ * Is this instance the coordinator?
351
+ *
352
+ * Coordinator status is determined from the coordinatorIdEnvVar environment variable.
353
+ * The coordinator handles finalization and cleanup of shard files.
354
+ *
355
+ * @returns true if this instance is the coordinator, false otherwise
356
+ */
357
+ isCoordinator() {
358
+ return this.#isCoordinator;
332
359
  }
333
360
  shard(shardId = getShardId()) {
334
361
  return new WriteAheadLogFile({