Implement event pub/sub messaging for federation to enable real-time event streaming between federated instances. Features: - Event subscription management (subscribe/unsubscribe) - Event publishing to subscribed instances - Event acknowledgment protocol - Server-side event filtering based on subscriptions - Full signature verification and connection validation Implementation: - FederationEventSubscription model for storing subscriptions - EventService with complete event lifecycle management - EventController with authenticated and public endpoints - EventMessage, EventAck, and SubscriptionDetails types - Comprehensive DTOs for all event operations API Endpoints: - POST /api/v1/federation/events/subscribe - POST /api/v1/federation/events/unsubscribe - POST /api/v1/federation/events/publish - GET /api/v1/federation/events/subscriptions - GET /api/v1/federation/events/messages - POST /api/v1/federation/incoming/event (public) - POST /api/v1/federation/incoming/event/ack (public) Testing: - 18 unit tests for EventService (89.09% coverage) - 11 unit tests for EventController (83.87% coverage) - All 29 tests passing - Follows TDD red-green-refactor cycle Technical Notes: - Reuses existing FederationMessage model with eventType field - Follows patterns from QueryService and CommandService - Uses existing signature and connection infrastructure - Supports hierarchical event type naming (e.g., "task.created") Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
110 lines
1.6 KiB
TypeScript
110 lines
1.6 KiB
TypeScript
/**
|
|
* Event DTOs
|
|
*
|
|
* Data Transfer Objects for event subscription and publishing.
|
|
*/
|
|
|
|
import { IsString, IsNotEmpty, IsOptional, IsObject } from "class-validator";
|
|
|
|
/**
|
|
* DTO for subscribing to an event type
|
|
*/
|
|
export class SubscribeToEventDto {
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
connectionId!: string;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
eventType!: string;
|
|
|
|
@IsOptional()
|
|
@IsObject()
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
/**
|
|
* DTO for unsubscribing from an event type
|
|
*/
|
|
export class UnsubscribeFromEventDto {
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
connectionId!: string;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
eventType!: string;
|
|
}
|
|
|
|
/**
|
|
* DTO for publishing an event
|
|
*/
|
|
export class PublishEventDto {
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
eventType!: string;
|
|
|
|
@IsObject()
|
|
@IsNotEmpty()
|
|
payload!: Record<string, unknown>;
|
|
}
|
|
|
|
/**
|
|
* DTO for incoming event request
|
|
*/
|
|
export class IncomingEventDto {
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
messageId!: string;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
instanceId!: string;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
eventType!: string;
|
|
|
|
@IsObject()
|
|
@IsNotEmpty()
|
|
payload!: Record<string, unknown>;
|
|
|
|
@IsNotEmpty()
|
|
timestamp!: number;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
signature!: string;
|
|
}
|
|
|
|
/**
|
|
* DTO for incoming event acknowledgment
|
|
*/
|
|
export class IncomingEventAckDto {
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
messageId!: string;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
correlationId!: string;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
instanceId!: string;
|
|
|
|
@IsNotEmpty()
|
|
received!: boolean;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
error?: string;
|
|
|
|
@IsNotEmpty()
|
|
timestamp!: number;
|
|
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
signature!: string;
|
|
}
|