Skip to content

Commit 8a8903f

Browse files
committed
refactor: fix merge
1 parent 8c2c51c commit 8a8903f

File tree

8 files changed

+75
-49
lines changed

8 files changed

+75
-49
lines changed

packages/utils/mocks/sink.mock.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
import type {
2-
RecoverResult,
3-
Recoverable,
4-
Sink,
5-
} from '../src/lib/sink-source.type';
1+
import type { AppendableSink, RecoverResult } from '../src/lib/wal';
62

7-
export class MockSink implements Sink<string, string> {
3+
export class MockAppendableSink implements AppendableSink<string> {
84
private writtenItems: string[] = [];
95
private closed = true;
106

117
open = vi.fn((): void => {
128
this.closed = false;
139
});
1410

15-
write = vi.fn((input: string): void => {
11+
append = vi.fn((input: string): void => {
1612
this.writtenItems.push(input);
1713
});
1814

@@ -24,6 +20,16 @@ export class MockSink implements Sink<string, string> {
2420
return this.closed;
2521
});
2622

23+
recover = vi.fn((): RecoverResult<string> => {
24+
return {
25+
records: [...this.writtenItems],
26+
errors: [],
27+
partialTail: null,
28+
};
29+
});
30+
31+
repack = vi.fn((): void => {});
32+
2733
encode = vi.fn((input: string): string => {
2834
return `${input}-${this.constructor.name}-encoded`;
2935
});
@@ -33,20 +39,14 @@ export class MockSink implements Sink<string, string> {
3339
});
3440
}
3541

36-
export class MockTraceEventFileSink extends MockSink implements Recoverable {
37-
recover = vi.fn(
38-
(): {
39-
records: unknown[];
40-
errors: { lineNo: number; line: string; error: Error }[];
41-
partialTail: string | null;
42-
} => {
43-
return {
44-
records: this.getWrittenItems(),
45-
errors: [],
46-
partialTail: null,
47-
} satisfies RecoverResult<string>;
48-
},
49-
);
42+
export class MockTraceEventFileSink extends MockAppendableSink {
43+
override recover = vi.fn((): RecoverResult<string> => {
44+
return {
45+
records: this.getWrittenItems(),
46+
errors: [],
47+
partialTail: null,
48+
};
49+
});
5050

5151
repack = vi.fn((): void => {});
5252

packages/utils/src/lib/performance-observer.int.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import { type PerformanceEntry, performance } from 'node:perf_hooks';
22
import type { MockedFunction } from 'vitest';
3-
import { MockFileSink } from '../../mocks/sink.mock';
3+
import { MockAppendableSink } from '../../mocks/sink.mock.js';
44
import {
55
type PerformanceObserverOptions,
66
PerformanceObserverSink,
77
} from './performance-observer.js';
88

99
describe('PerformanceObserverSink', () => {
1010
let encode: MockedFunction<(entry: PerformanceEntry) => string[]>;
11-
let sink: MockFileSink;
11+
let sink: MockAppendableSink;
1212
let options: PerformanceObserverOptions<string>;
1313

1414
const awaitObserverCallback = () =>
1515
new Promise(resolve => setTimeout(resolve, 10));
1616

1717
beforeEach(() => {
18-
sink = new MockFileSink();
18+
sink = new MockAppendableSink();
1919
sink.open();
2020
encode = vi.fn((entry: PerformanceEntry) => [
2121
`${entry.name}:${entry.entryType}`,
@@ -139,9 +139,9 @@ describe('PerformanceObserverSink', () => {
139139
});
140140

141141
it('keeps items in queue when sink write fails', async () => {
142-
const failingSink = new MockSink();
142+
const failingSink = new MockAppendableSink();
143143
failingSink.open();
144-
failingSink.write.mockImplementation(() => {
144+
failingSink.append.mockImplementation(() => {
145145
throw new Error('Sink write failed');
146146
});
147147

@@ -163,7 +163,7 @@ describe('PerformanceObserverSink', () => {
163163
});
164164

165165
it('keeps items in queue when sink is closed during flush', async () => {
166-
const closedSink = new MockSink();
166+
const closedSink = new MockAppendableSink();
167167
closedSink.open();
168168
closedSink.close();
169169

packages/utils/src/lib/performance-observer.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
} from 'node:perf_hooks';
66
import { isEnvVarEnabled } from './env.js';
77
import { PROFILER_DEBUG_ENV_VAR } from './profiler/constants.js';
8-
import type { Buffered, Observer, Sink } from './sink-source.type';
98
import type { AppendableSink } from './wal.js';
109

1110
/**
@@ -85,9 +84,9 @@ export function validateFlushThreshold(
8584
export type PerformanceObserverOptions<T> = {
8685
/**
8786
* The sink where encoded performance entries will be written.
88-
* Must implement the Sink interface for handling the encoded data.
87+
* Must implement the AppendableSink interface for handling the encoded data.
8988
*/
90-
sink: Sink<T, unknown>;
89+
sink: AppendableSink<T>;
9190

9291
/**
9392
* Function that encodes raw PerformanceEntry objects into domain-specific types.
@@ -178,7 +177,7 @@ export class PerformanceObserverSink<T> {
178177
#maxQueueSize: number;
179178

180179
/** The target sink where encoded performance data is written */
181-
#sink: Sink<T, unknown>;
180+
#sink: AppendableSink<T>;
182181

183182
/** Node.js PerformanceObserver instance, undefined when not subscribed */
184183
#observer: PerformanceObserver | undefined;

packages/utils/src/lib/performance-observer.unit.test.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { type PerformanceEntry, performance } from 'node:perf_hooks';
22
import type { MockedFunction } from 'vitest';
33
import { MockPerformanceObserver } from '@code-pushup/test-utils';
4-
import { MockFileSink } from '../../mocks/sink.mock';
4+
import { MockAppendableSink } from '../../mocks/sink.mock';
55
import {
66
DEFAULT_FLUSH_THRESHOLD,
77
DEFAULT_MAX_QUEUE_SIZE,
88
type PerformanceObserverOptions,
99
PerformanceObserverSink,
1010
validateFlushThreshold,
1111
} from './performance-observer.js';
12-
import type { Codec } from './wal.js';
1312

1413
describe('validateFlushThreshold', () => {
1514
it.each([
@@ -56,12 +55,12 @@ describe('validateFlushThreshold', () => {
5655

5756
describe('PerformanceObserverSink', () => {
5857
let encodePerfEntry: MockedFunction<(entry: PerformanceEntry) => string[]>;
59-
let sink: MockFileSink;
58+
let sink: MockAppendableSink;
6059
let options: PerformanceObserverOptions<string>;
6160

6261
beforeEach(() => {
6362
vi.clearAllMocks();
64-
sink = new MockFileSink();
63+
sink = new MockAppendableSink();
6564
sink.open();
6665
encodePerfEntry = vi.fn((entry: PerformanceEntry) => [
6766
`${entry.name}:${entry.entryType}`,
@@ -669,17 +668,27 @@ describe('PerformanceObserverSink', () => {
669668
const customSink = {
670669
// eslint-disable-next-line functional/immutable-data
671670
append: (item: string) => collectedItems.push(item),
671+
isClosed: () => false,
672+
recover: () => ({
673+
records: [],
674+
errors: [],
675+
partialTail: null,
676+
}),
677+
repack: () => {},
672678
};
673679

674680
const observer = new PerformanceObserverSink({
675681
sink: customSink,
676-
encode: (entry: PerformanceEntry) => [`${entry.name}:${entry.duration}`],
682+
encodePerfEntry: (entry: PerformanceEntry) => [
683+
`${entry.name}:${entry.duration}`,
684+
],
677685
});
678686

679687
observer.subscribe();
680688

681689
const mockObserver = MockPerformanceObserver.lastInstance();
682-
mockObserver?.emitMark('test-mark');
690+
performance.mark('test-mark');
691+
mockObserver?.triggerObserverCallback();
683692

684693
observer.flush();
685694

packages/utils/src/lib/profiler/profiler.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
type PerformanceObserverOptions,
77
PerformanceObserverSink,
88
} from '../performance-observer.js';
9-
import type { Recoverable, Sink } from '../sink-source.type.js';
109
import { objectToEntries } from '../transform.js';
1110
import {
1211
type ActionTrackConfigs,
@@ -23,6 +22,7 @@ import type {
2322
EntryMeta,
2423
MarkerPayload,
2524
} from '../user-timing-extensibility-api.type.js';
25+
import type { AppendableSink } from '../wal.js';
2626
import {
2727
PROFILER_DEBUG_ENV_VAR,
2828
PROFILER_ENABLED_ENV_VAR,
@@ -264,7 +264,7 @@ export type NodejsProfilerOptions<
264264
/** Sink for buffering and flushing performance data
265265
* @NOTE this is dummy code and will be replaced by PR #1210
266266
**/
267-
sink: Sink<DomainEvents, unknown> & Recoverable;
267+
sink: AppendableSink<DomainEvents>;
268268

269269
/**
270270
* Name of the environment variable to check for debug mode.
@@ -297,7 +297,7 @@ export class NodejsProfiler<
297297
ActionTrackEntryPayload
298298
>,
299299
> extends Profiler<Tracks> {
300-
#sink: Sink<DomainEvents, unknown> & Recoverable;
300+
#sink: AppendableSink<DomainEvents>;
301301
#performanceObserverSink: PerformanceObserverSink<DomainEvents>;
302302
#state: 'idle' | 'running' | 'closed' = 'idle';
303303
#debug: boolean;
@@ -377,15 +377,15 @@ export class NodejsProfiler<
377377
switch (transition) {
378378
case 'idle->running':
379379
super.setEnabled(true);
380-
this.#sink.open();
380+
this.#sink.open?.();
381381
this.#performanceObserverSink.subscribe();
382382
break;
383383

384384
case 'running->idle':
385385
case 'running->closed':
386386
super.setEnabled(false);
387387
this.#performanceObserverSink.unsubscribe();
388-
this.#sink.close();
388+
this.#sink.close?.();
389389
break;
390390

391391
case 'idle->closed':

packages/utils/src/lib/profiler/profiler.unit.test.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
44
import { MockTraceEventFileSink } from '../../../mocks/sink.mock.js';
55
import type { PerformanceEntryEncoder } from '../performance-observer.js';
66
import * as PerfObserverModule from '../performance-observer.js';
7-
import type { ActionTrackEntryPayload } from '../user-timing-extensibility-api.type.js';
7+
import type {
8+
ActionTrackEntryPayload,
9+
UserTimingDetail,
10+
} from '../user-timing-extensibility-api.type.js';
811
import {
912
NodejsProfiler,
1013
type NodejsProfilerOptions,
@@ -23,6 +26,7 @@ describe('getProfilerId', () => {
2326
);
2427
});
2528
});
29+
2630
describe('Profiler', () => {
2731
const getProfiler = (overrides?: Partial<ProfilerOptions>) =>
2832
new Profiler({
@@ -491,8 +495,8 @@ describe('NodejsProfiler', () => {
491495

492496
const mockPerfObserverSink = {
493497
subscribe: vi.fn(),
494-
unsubscribe: vi.fn(function (this: typeof mockPerfObserverSink) {
495-
this.flush();
498+
unsubscribe: vi.fn(() => {
499+
mockPerfObserverSink.flush();
496500
}),
497501
isSubscribed: vi.fn().mockReturnValue(false),
498502
encode: vi.fn(),
@@ -1212,9 +1216,10 @@ describe('NodejsProfiler', () => {
12121216
// Verify marker was created with correct name and includes stats in detail
12131217
expect(transitionMark?.name).toBe('idle->running');
12141218
expect(transitionMark?.detail).toBeDefined();
1215-
expect(transitionMark?.detail.devtools).toBeDefined();
1216-
expect(transitionMark?.detail.devtools.dataType).toBe('marker');
1217-
expect(transitionMark?.detail.devtools.properties).toBeDefined();
1219+
const detail = transitionMark?.detail as UserTimingDetail;
1220+
expect(detail.devtools).toBeDefined();
1221+
expect(detail.devtools?.dataType).toBe('marker');
1222+
expect(detail.devtools?.properties).toBeDefined();
12181223
});
12191224

12201225
it('setEnabled override: should enable profiling when setEnabled(true)', () => {

packages/utils/src/lib/sink-source.type.ts

Whitespace-only changes.

packages/utils/src/lib/wal.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,21 @@ export type InvalidEntry<O = string> = { __invalid: true; raw: O };
2121
* Interface for sinks that can append items.
2222
* Allows for different types of appendable storage (WAL, in-memory, etc.)
2323
*/
24-
export type AppendableSink<T> = {
24+
export type AppendableSink<T> = Recoverable & {
2525
append: (item: T) => void;
26+
isClosed: () => boolean;
27+
open?: () => void;
28+
close?: () => void;
29+
};
30+
31+
/**
32+
* Interface for sinks that support recovery operations.
33+
* Represents the recoverable subset of AppendableSink functionality.
34+
*/
35+
export type Recoverable = {
36+
recover: () => RecoverResult<unknown>;
37+
repack: (out?: string) => void;
38+
finalize?: (opt?: Record<string, unknown>) => void;
2639
};
2740

2841
/**

0 commit comments

Comments
 (0)