Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
176 lines
4.3 KiB
TypeScript
176 lines
4.3 KiB
TypeScript
/**
|
|
* In-Memory Health Event Publisher
|
|
*
|
|
* Tracks health-related events for testing purposes.
|
|
* This publisher allows verification of event emission patterns
|
|
* without requiring external event bus infrastructure.
|
|
*/
|
|
|
|
import {
|
|
HealthEventPublisher,
|
|
HealthCheckCompletedEvent,
|
|
HealthCheckFailedEvent,
|
|
HealthCheckTimeoutEvent,
|
|
ConnectedEvent,
|
|
DisconnectedEvent,
|
|
DegradedEvent,
|
|
CheckingEvent,
|
|
} from '../../core/health/ports/HealthEventPublisher';
|
|
|
|
export interface HealthCheckCompletedEventWithType {
|
|
type: 'HealthCheckCompleted';
|
|
healthy: boolean;
|
|
responseTime: number;
|
|
timestamp: Date;
|
|
endpoint?: string;
|
|
}
|
|
|
|
export interface HealthCheckFailedEventWithType {
|
|
type: 'HealthCheckFailed';
|
|
error: string;
|
|
timestamp: Date;
|
|
endpoint?: string;
|
|
}
|
|
|
|
export interface HealthCheckTimeoutEventWithType {
|
|
type: 'HealthCheckTimeout';
|
|
timestamp: Date;
|
|
endpoint?: string;
|
|
}
|
|
|
|
export interface ConnectedEventWithType {
|
|
type: 'Connected';
|
|
timestamp: Date;
|
|
responseTime: number;
|
|
}
|
|
|
|
export interface DisconnectedEventWithType {
|
|
type: 'Disconnected';
|
|
timestamp: Date;
|
|
consecutiveFailures: number;
|
|
}
|
|
|
|
export interface DegradedEventWithType {
|
|
type: 'Degraded';
|
|
timestamp: Date;
|
|
reliability: number;
|
|
}
|
|
|
|
export interface CheckingEventWithType {
|
|
type: 'Checking';
|
|
timestamp: Date;
|
|
}
|
|
|
|
export type HealthEvent =
|
|
| HealthCheckCompletedEventWithType
|
|
| HealthCheckFailedEventWithType
|
|
| HealthCheckTimeoutEventWithType
|
|
| ConnectedEventWithType
|
|
| DisconnectedEventWithType
|
|
| DegradedEventWithType
|
|
| CheckingEventWithType;
|
|
|
|
export class InMemoryHealthEventPublisher implements HealthEventPublisher {
|
|
private events: HealthEvent[] = [];
|
|
private shouldFail: boolean = false;
|
|
|
|
/**
|
|
* Publish a health check completed event
|
|
*/
|
|
async publishHealthCheckCompleted(event: HealthCheckCompletedEvent): Promise<void> {
|
|
if (this.shouldFail) throw new Error('Event publisher failed');
|
|
this.events.push({ type: 'HealthCheckCompleted', ...event });
|
|
}
|
|
|
|
/**
|
|
* Publish a health check failed event
|
|
*/
|
|
async publishHealthCheckFailed(event: HealthCheckFailedEvent): Promise<void> {
|
|
if (this.shouldFail) throw new Error('Event publisher failed');
|
|
this.events.push({ type: 'HealthCheckFailed', ...event });
|
|
}
|
|
|
|
/**
|
|
* Publish a health check timeout event
|
|
*/
|
|
async publishHealthCheckTimeout(event: HealthCheckTimeoutEvent): Promise<void> {
|
|
if (this.shouldFail) throw new Error('Event publisher failed');
|
|
this.events.push({ type: 'HealthCheckTimeout', ...event });
|
|
}
|
|
|
|
/**
|
|
* Publish a connected event
|
|
*/
|
|
async publishConnected(event: ConnectedEvent): Promise<void> {
|
|
if (this.shouldFail) throw new Error('Event publisher failed');
|
|
this.events.push({ type: 'Connected', ...event });
|
|
}
|
|
|
|
/**
|
|
* Publish a disconnected event
|
|
*/
|
|
async publishDisconnected(event: DisconnectedEvent): Promise<void> {
|
|
if (this.shouldFail) throw new Error('Event publisher failed');
|
|
this.events.push({ type: 'Disconnected', ...event });
|
|
}
|
|
|
|
/**
|
|
* Publish a degraded event
|
|
*/
|
|
async publishDegraded(event: DegradedEvent): Promise<void> {
|
|
if (this.shouldFail) throw new Error('Event publisher failed');
|
|
this.events.push({ type: 'Degraded', ...event });
|
|
}
|
|
|
|
/**
|
|
* Publish a checking event
|
|
*/
|
|
async publishChecking(event: CheckingEvent): Promise<void> {
|
|
if (this.shouldFail) throw new Error('Event publisher failed');
|
|
this.events.push({ type: 'Checking', ...event });
|
|
}
|
|
|
|
/**
|
|
* Get all published events
|
|
*/
|
|
getEvents(): HealthEvent[] {
|
|
return [...this.events];
|
|
}
|
|
|
|
/**
|
|
* Get events by type
|
|
*/
|
|
getEventsByType<T extends HealthEvent['type']>(type: T): Extract<HealthEvent, { type: T }>[] {
|
|
return this.events.filter((event): event is Extract<HealthEvent, { type: T }> => event.type === type);
|
|
}
|
|
|
|
/**
|
|
* Get the count of events
|
|
*/
|
|
getEventCount(): number {
|
|
return this.events.length;
|
|
}
|
|
|
|
/**
|
|
* Get the count of events by type
|
|
*/
|
|
getEventCountByType(type: HealthEvent['type']): number {
|
|
return this.events.filter(event => event.type === type).length;
|
|
}
|
|
|
|
/**
|
|
* Clear all published events
|
|
*/
|
|
clear(): void {
|
|
this.events = [];
|
|
this.shouldFail = false;
|
|
}
|
|
|
|
/**
|
|
* Configure the publisher to fail on publish
|
|
*/
|
|
setShouldFail(shouldFail: boolean): void {
|
|
this.shouldFail = shouldFail;
|
|
}
|
|
}
|