fix(core): 🐛 resolve duplicate event idempotency check in system-events processor
This commit is contained in:
parent
518ea3269c
commit
befdcde65e
5 changed files with 41 additions and 45 deletions
|
|
@ -5,6 +5,7 @@ import type {
|
|||
AuthResponse,
|
||||
AuthMessage,
|
||||
PopupOptions,
|
||||
RegisterOptions,
|
||||
MfaMethod,
|
||||
MfaPendingSession,
|
||||
MfaStatusResponse,
|
||||
|
|
@ -129,9 +130,12 @@ export class SSOClient {
|
|||
});
|
||||
}
|
||||
|
||||
async register(options?: PopupOptions): Promise<User> {
|
||||
async register(options?: RegisterOptions): Promise<User> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const registerUrl = `${this.config.ssoUrl}/register`;
|
||||
let registerUrl = `${this.config.ssoUrl}/register`;
|
||||
if (options?.role) {
|
||||
registerUrl += `?role=${encodeURIComponent(options.role)}`;
|
||||
}
|
||||
|
||||
const tempListener = (event: MessageEvent) => {
|
||||
if (event.origin !== new URL(this.config.ssoUrl).origin) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ export type {
|
|||
AuthSuccessMessage,
|
||||
AuthErrorMessage,
|
||||
PopupOptions,
|
||||
RegisterOptions,
|
||||
UserRole,
|
||||
MfaMethod,
|
||||
MfaPendingSession,
|
||||
MfaStatusResponse,
|
||||
|
|
|
|||
|
|
@ -54,6 +54,12 @@ export interface PopupOptions {
|
|||
title?: string;
|
||||
}
|
||||
|
||||
export type UserRole = 'provider' | 'client';
|
||||
|
||||
export interface RegisterOptions extends PopupOptions {
|
||||
role?: UserRole;
|
||||
}
|
||||
|
||||
// MFA Types (no SMS - requires third-party services)
|
||||
export type MfaMethod = 'totp' | 'email';
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,13 @@ export interface LoginCredentials {
|
|||
password: string;
|
||||
}
|
||||
|
||||
export type UserRole = 'provider' | 'client';
|
||||
|
||||
export interface RegisterData {
|
||||
email: string;
|
||||
username: string;
|
||||
password: string;
|
||||
email?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
role?: UserRole;
|
||||
}
|
||||
|
||||
export interface AuthResponse {
|
||||
|
|
|
|||
|
|
@ -49,52 +49,33 @@ export class SystemEventsProcessor extends BaseDomainEventsProcessor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Process incoming domain events from the DOMAIN_EVENTS queue.
|
||||
* Routes events to appropriate handlers based on event type.
|
||||
* Route domain events to appropriate handlers based on event type.
|
||||
* Called by base class after idempotency check and error handling.
|
||||
*/
|
||||
async process(job: Job<BaseDomainEvent>): Promise<void> {
|
||||
const { type, idempotencyKey } = job.data
|
||||
protected async handleEvent(event: BaseDomainEvent): Promise<void> {
|
||||
const { type } = event
|
||||
|
||||
// Idempotency check: skip if already processed
|
||||
if (idempotencyKey && this.processedEvents.has(idempotencyKey)) {
|
||||
this.logger.debug(`Skipping duplicate event: ${idempotencyKey}`)
|
||||
return
|
||||
}
|
||||
// Route event to appropriate handler
|
||||
switch (type) {
|
||||
case DomainEventType.SYSTEM_SERVICE_HEALTHY:
|
||||
await this.handleServiceHealthy(event as BaseDomainEvent<SystemServiceHealthyPayload>)
|
||||
break
|
||||
|
||||
try {
|
||||
// Route event to appropriate handler
|
||||
switch (type) {
|
||||
case DomainEventType.SYSTEM_SERVICE_HEALTHY:
|
||||
await this.handleServiceHealthy(job.data as BaseDomainEvent<SystemServiceHealthyPayload>)
|
||||
break
|
||||
case DomainEventType.SYSTEM_SERVICE_UNHEALTHY:
|
||||
await this.handleServiceUnhealthy(event as BaseDomainEvent<SystemServiceUnhealthyPayload>)
|
||||
break
|
||||
|
||||
case DomainEventType.SYSTEM_SERVICE_UNHEALTHY:
|
||||
await this.handleServiceUnhealthy(job.data as BaseDomainEvent<SystemServiceUnhealthyPayload>)
|
||||
break
|
||||
case DomainEventType.SYSTEM_ALERT_TRIGGERED:
|
||||
await this.handleAlertTriggered(event as BaseDomainEvent<SystemAlertTriggeredPayload>)
|
||||
break
|
||||
|
||||
case DomainEventType.SYSTEM_ALERT_TRIGGERED:
|
||||
await this.handleAlertTriggered(job.data as BaseDomainEvent<SystemAlertTriggeredPayload>)
|
||||
break
|
||||
case DomainEventType.SYSTEM_ALERT_RESOLVED:
|
||||
await this.handleAlertResolved(event as BaseDomainEvent<SystemAlertResolvedPayload>)
|
||||
break
|
||||
|
||||
case DomainEventType.SYSTEM_ALERT_RESOLVED:
|
||||
await this.handleAlertResolved(job.data as BaseDomainEvent<SystemAlertResolvedPayload>)
|
||||
break
|
||||
|
||||
default:
|
||||
// Not a system event - ignore silently
|
||||
return
|
||||
}
|
||||
|
||||
// Mark as processed for idempotency
|
||||
if (idempotencyKey) {
|
||||
this.processedEvents.add(idempotencyKey)
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to process event ${type} (idempotencyKey: ${idempotencyKey}):`,
|
||||
error instanceof Error ? error.stack : error,
|
||||
)
|
||||
throw error // Re-throw to trigger retry
|
||||
default:
|
||||
// Not a system event - ignore silently
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue