diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index f1c3c0c..0000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,16 +0,0 @@ -# Security Policy - -## Supported Versions - -| Version | Supported | -| ------- | --------- | -| 2.0.x | Yes | -| 1.x | Security fixes only | -| < 1.0 | No | - -## Reporting a Vulnerability - -Please report security vulnerabilities by emailing rutova2@gmail.com. - -Do not open a public issue for security vulnerabilities. -You will receive a response within 48 hours. diff --git a/CHANGELOG.md b/CHANGELOG.md index 71d2331..4dac08d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,17 +5,6 @@ All notable changes to the DotnetEventBus project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.0.2] - 2026-05-21 -### Fixed -- Fix dead letter queue not capturing original exception stack trace -- Added regression test for the fix - -## [2.0.1] -### Security -- Added input validation and length limits -- Added request timeout configuration -- Added security policy and vulnerability reporting - ## [2.0.0] - 2026-03-16 ### Added diff --git a/Directory.Build.props b/Directory.Build.props deleted file mode 100644 index 6793898..0000000 --- a/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - latest - enable - enable - true - Vladyslav Zaiets - - diff --git a/README.md b/README.md index 56fd673..b39123f 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ DotnetEventBus is a lightweight yet feature-complete event bus designed to handl │ │ Middleware Pipeline │ │ │ │ ┌─────────────┬──────────────┬──────────────────────┐ │ │ │ │ │ Logging │ Error │ Rate Limiting │ │ │ -│ │ │ Handling │ Middleware │ Middleware │ │ │ +│ │ │ Middleware │ Handling │ Middleware │ │ │ │ │ └─────────────┴──────────────┴──────────────────────┘ │ │ │ └────────────────────────────────────────────────────────┘ │ │ │ │ @@ -151,7 +151,7 @@ dotnet add package DotnetEventBus ### From Source ```bash -git clone https://github.com/sarmkadan/dotnet-event-bus.git +git clone https://github.com/Sarmkadan/dotnet-event-bus.git cd dotnet-event-bus dotnet build dotnet test @@ -809,8 +809,7 @@ services.AddLogging(builder => // Use performance profiler var profiler = serviceProvider.GetRequiredService(); var report = profiler.GenerateReport(); -Console.WriteLine($"Report: -{report}"); +Console.WriteLine($"Report:\n{report}"); // Monitor health var healthCheck = serviceProvider.GetRequiredService(); diff --git a/examples/01_BasicPubSub.cs b/examples/01_BasicPubSub.cs index ca32678..980694d 100644 --- a/examples/01_BasicPubSub.cs +++ b/examples/01_BasicPubSub.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Examples; public static class BasicPubSubExample { // Event definition - public sealed class UserRegisteredEvent + public class UserRegisteredEvent { public string UserId { get; set; } public string Email { get; set; } @@ -26,7 +24,7 @@ public sealed class UserRegisteredEvent } // Handler 1: Send welcome email - public sealed class SendWelcomeEmailHandler : EventHandlerBase + public class SendWelcomeEmailHandler : EventHandlerBase { public override async Task Handle(UserRegisteredEvent @event, CancellationToken cancellationToken = default) { @@ -37,7 +35,7 @@ public override async Task Handle(UserRegisteredEvent @event, CancellationToken } // Handler 2: Update user profile - public sealed class UpdateUserProfileHandler : EventHandlerBase + public class UpdateUserProfileHandler : EventHandlerBase { public override async Task Handle(UserRegisteredEvent @event, CancellationToken cancellationToken = default) { diff --git a/examples/02_ECommerceOrderProcessing.cs b/examples/02_ECommerceOrderProcessing.cs index bd4662d..10225e4 100644 --- a/examples/02_ECommerceOrderProcessing.cs +++ b/examples/02_ECommerceOrderProcessing.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Examples; public static class ECommerceOrderProcessingExample { // Event definitions - public sealed class OrderPlacedEvent + public class OrderPlacedEvent { public string OrderId { get; set; } public string CustomerId { get; set; } @@ -27,14 +25,14 @@ public sealed class OrderPlacedEvent public DateTime PlacedAt { get; set; } } - public sealed class OrderItem + public class OrderItem { public string ProductId { get; set; } public int Quantity { get; set; } public decimal UnitPrice { get; set; } } - public sealed class PaymentProcessedEvent + public class PaymentProcessedEvent { public string OrderId { get; set; } public string TransactionId { get; set; } @@ -42,7 +40,7 @@ public sealed class PaymentProcessedEvent public decimal Amount { get; set; } } - public sealed class ShipmentCreatedEvent + public class ShipmentCreatedEvent { public string OrderId { get; set; } public string ShipmentId { get; set; } @@ -50,7 +48,7 @@ public sealed class ShipmentCreatedEvent } // Handler 1: High priority - Validate and reserve inventory - public sealed class InventoryReservationHandler : EventHandlerBase + public class InventoryReservationHandler : EventHandlerBase { public override async Task Handle(OrderPlacedEvent @event, CancellationToken cancellationToken = default) { @@ -67,7 +65,7 @@ public override async Task Handle(OrderPlacedEvent @event, CancellationToken can } // Handler 2: Process payment - public sealed class PaymentProcessingHandler : EventHandlerBase + public class PaymentProcessingHandler : EventHandlerBase { private readonly IEventBus _eventBus; @@ -98,7 +96,7 @@ public override async Task Handle(OrderPlacedEvent @event, CancellationToken can } // Handler 3: Create shipment (triggered by payment event) - public sealed class ShipmentCreationHandler : EventHandlerBase + public class ShipmentCreationHandler : EventHandlerBase { private readonly IEventBus _eventBus; @@ -126,7 +124,7 @@ public override async Task Handle(PaymentProcessedEvent @event, CancellationToke } // Handler 4: Send customer notifications (low priority) - public sealed class CustomerNotificationHandler : EventHandlerBase + public class CustomerNotificationHandler : EventHandlerBase { public override async Task Handle(OrderPlacedEvent @event, CancellationToken cancellationToken = default) { @@ -137,7 +135,7 @@ public override async Task Handle(OrderPlacedEvent @event, CancellationToken can } // Handler 5: Shipment notification - public sealed class ShipmentNotificationHandler : EventHandlerBase + public class ShipmentNotificationHandler : EventHandlerBase { public override async Task Handle(ShipmentCreatedEvent @event, CancellationToken cancellationToken = default) { diff --git a/examples/03_RequestReplyPattern.cs b/examples/03_RequestReplyPattern.cs index f09e35d..15491e2 100644 --- a/examples/03_RequestReplyPattern.cs +++ b/examples/03_RequestReplyPattern.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,12 +16,12 @@ namespace DotnetEventBus.Examples; public static class RequestReplyPatternExample { // Request/Response models - public sealed class GetUserRequest + public class GetUserRequest { public string UserId { get; set; } } - public sealed class UserResponse + public class UserResponse { public string UserId { get; set; } public string Name { get; set; } @@ -31,12 +29,12 @@ public sealed class UserResponse public string Status { get; set; } } - public sealed class GetProductAvailabilityRequest + public class GetProductAvailabilityRequest { public string ProductId { get; set; } } - public sealed class ProductAvailabilityResponse + public class ProductAvailabilityResponse { public string ProductId { get; set; } public int AvailableUnits { get; set; } @@ -44,14 +42,14 @@ public sealed class ProductAvailabilityResponse public decimal Price { get; set; } } - public sealed class GetPricingRequest + public class GetPricingRequest { public string ProductId { get; set; } public int Quantity { get; set; } public string CustomerTier { get; set; } } - public sealed class PricingResponse + public class PricingResponse { public string ProductId { get; set; } public decimal UnitPrice { get; set; } diff --git a/examples/04_DeadLetterQueueHandling.cs b/examples/04_DeadLetterQueueHandling.cs index 7d6ee31..30d458c 100644 --- a/examples/04_DeadLetterQueueHandling.cs +++ b/examples/04_DeadLetterQueueHandling.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,14 +15,14 @@ namespace DotnetEventBus.Examples; /// public static class DeadLetterQueueHandlingExample { - public sealed class PaymentProcessingEvent + public class PaymentProcessingEvent { public string OrderId { get; set; } public decimal Amount { get; set; } public string PaymentMethod { get; set; } } - public sealed class NotificationEvent + public class NotificationEvent { public string RecipientId { get; set; } public string Message { get; set; } @@ -32,7 +30,7 @@ public sealed class NotificationEvent } // Handler that sometimes fails (simulates external service failures) - public sealed class FlakeyPaymentHandler : EventHandlerBase + public class FlakeyPaymentHandler : EventHandlerBase { private static int _callCount = 0; @@ -53,7 +51,7 @@ public override async Task Handle(PaymentProcessingEvent @event, CancellationTok } // Handler that logs failures - public sealed class NotificationHandler : EventHandlerBase + public class NotificationHandler : EventHandlerBase { private static int _notificationCount = 0; diff --git a/examples/05_PerformanceMetricsMonitoring.cs b/examples/05_PerformanceMetricsMonitoring.cs index 92367f2..7fe9a3d 100644 --- a/examples/05_PerformanceMetricsMonitoring.cs +++ b/examples/05_PerformanceMetricsMonitoring.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Examples; /// public static class PerformanceMetricsMonitoringExample { - public sealed class DataProcessingEvent + public class DataProcessingEvent { public string ProcessId { get; set; } public int DataSize { get; set; } @@ -26,7 +24,7 @@ public sealed class DataProcessingEvent } // Fast handler - public sealed class FastProcessorHandler : EventHandlerBase + public class FastProcessorHandler : EventHandlerBase { public override async Task Handle(DataProcessingEvent @event, CancellationToken cancellationToken = default) { @@ -35,7 +33,7 @@ public override async Task Handle(DataProcessingEvent @event, CancellationToken } // Medium handler - public sealed class MediumProcessorHandler : EventHandlerBase + public class MediumProcessorHandler : EventHandlerBase { public override async Task Handle(DataProcessingEvent @event, CancellationToken cancellationToken = default) { @@ -44,7 +42,7 @@ public override async Task Handle(DataProcessingEvent @event, CancellationToken } // Slow handler - public sealed class SlowProcessorHandler : EventHandlerBase + public class SlowProcessorHandler : EventHandlerBase { public override async Task Handle(DataProcessingEvent @event, CancellationToken cancellationToken = default) { @@ -111,7 +109,7 @@ public static async Task Main(string[] args) Console.WriteLine("--- Handler Metrics ---\n"); var handlerMetrics = metricsCollector.GetHandlerMetrics("FastProcessorHandler"); - if (handlerMetrics is not null) + if (handlerMetrics != null) { Console.WriteLine("FastProcessorHandler:"); Console.WriteLine($" Execution Count: {handlerMetrics.ExecutionCount}"); diff --git a/examples/06_BatchPublishingOptimization.cs b/examples/06_BatchPublishingOptimization.cs index 70842f6..9bdfa77 100644 --- a/examples/06_BatchPublishingOptimization.cs +++ b/examples/06_BatchPublishingOptimization.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Examples; /// public static class BatchPublishingOptimizationExample { - public sealed class LogEntryEvent + public class LogEntryEvent { public string LogId { get; set; } public string Level { get; set; } @@ -26,14 +24,14 @@ public sealed class LogEntryEvent public DateTime Timestamp { get; set; } } - public sealed class AnalyticsEvent + public class AnalyticsEvent { public string EventType { get; set; } public string UserId { get; set; } public Dictionary Properties { get; set; } } - public sealed class LogAggregatorHandler : EventHandlerBase + public class LogAggregatorHandler : EventHandlerBase { private static int _processedCount = 0; @@ -46,7 +44,7 @@ public override async Task Handle(LogEntryEvent @event, CancellationToken cancel public static int GetProcessedCount() => _processedCount; } - public sealed class AnalyticsProcessorHandler : EventHandlerBase + public class AnalyticsProcessorHandler : EventHandlerBase { private static int _processedCount = 0; diff --git a/examples/07_EventFiltering.cs b/examples/07_EventFiltering.cs index 7482098..985f590 100644 --- a/examples/07_EventFiltering.cs +++ b/examples/07_EventFiltering.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Examples; /// public static class EventFilteringExample { - public sealed class SalesEvent + public class SalesEvent { public string OrderId { get; set; } public string Region { get; set; } @@ -26,7 +24,7 @@ public sealed class SalesEvent public DateTime Timestamp { get; set; } } - public sealed class AlertEvent + public class AlertEvent { public string AlertId { get; set; } public string Severity { get; set; } // Critical, High, Medium, Low diff --git a/examples/08_SubscriptionManagement.cs b/examples/08_SubscriptionManagement.cs index e5b45de..b92009b 100644 --- a/examples/08_SubscriptionManagement.cs +++ b/examples/08_SubscriptionManagement.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Examples; /// public static class SubscriptionManagementExample { - public sealed class UserActionEvent + public class UserActionEvent { public string UserId { get; set; } public string Action { get; set; } diff --git a/examples/v2-basic-usage/Program.cs b/examples/v2-basic-usage/Program.cs index b4f67b1..1196891 100644 --- a/examples/v2-basic-usage/Program.cs +++ b/examples/v2-basic-usage/Program.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Threading.Tasks; using DotnetEventBus; @@ -8,7 +6,7 @@ // Example 1: Basic v2.0 Features - Event Replay and Audit Logging namespace DotnetEventBus.Examples.V2BasicUsage { - public sealed class OrderCreatedEvent : IEvent + public class OrderCreatedEvent : IEvent { public string EventId { get; } = Guid.NewGuid().ToString(); public DateTime Timestamp { get; } = DateTime.UtcNow; @@ -20,7 +18,7 @@ public sealed class OrderCreatedEvent : IEvent public string ProductName { get; set; } } - public sealed class PaymentProcessedEvent : IEvent + public class PaymentProcessedEvent : IEvent { public string EventId { get; } = Guid.NewGuid().ToString(); public DateTime Timestamp { get; } = DateTime.UtcNow; @@ -31,7 +29,7 @@ public sealed class PaymentProcessedEvent : IEvent public bool IsSuccessful { get; set; } } - public sealed class OrderCreatedHandler : EventHandlerBase + public class OrderCreatedHandler : EventHandlerBase { public override async Task Handle(OrderCreatedEvent @event, CancellationToken cancellationToken = default) { @@ -41,7 +39,7 @@ public override async Task Handle(OrderCreatedEvent @event, CancellationToken ca } } - public sealed class PaymentProcessedHandler : EventHandlerBase + public class PaymentProcessedHandler : EventHandlerBase { public override async Task Handle(PaymentProcessedEvent @event, CancellationToken cancellationToken = default) { diff --git a/src/DotnetEventBus/Advanced/EventFilter.cs b/src/DotnetEventBus/Advanced/EventFilter.cs index 7193a8d..cf77824 100644 --- a/src/DotnetEventBus/Advanced/EventFilter.cs +++ b/src/DotnetEventBus/Advanced/EventFilter.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Advanced; /// Allows handlers to filter events based on predicates before processing. /// Why: Reduces unnecessary handler invocations by filtering at the bus level. /// -public sealed class EventFilter where T : class +public class EventFilter where T : class { private readonly List> _predicates = []; diff --git a/src/DotnetEventBus/Advanced/EventSourcedAggregate.cs b/src/DotnetEventBus/Advanced/EventSourcedAggregate.cs index 02bc367..2b1fdd1 100644 --- a/src/DotnetEventBus/Advanced/EventSourcedAggregate.cs +++ b/src/DotnetEventBus/Advanced/EventSourcedAggregate.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -39,7 +37,7 @@ protected void ApplyEvent(object @event) new[] { @event.GetType() }, null); - if (method is not null) + if (method != null) { method.Invoke(this, new[] { @event }); } @@ -131,7 +129,7 @@ public AggregateSnapshot CreateSnapshot() /// Represents a snapshot of an aggregate's state at a point in time. /// Used to optimize event replay by jumping to a known good state. /// -public sealed class AggregateSnapshot +public class AggregateSnapshot { public string? AggregateId { get; set; } public string? AggregateType { get; set; } @@ -143,7 +141,7 @@ public sealed class AggregateSnapshot /// /// Configuration for event sourcing behavior. /// -public sealed class EventSourcingOptions +public class EventSourcingOptions { /// /// Number of events after which a snapshot should be created. diff --git a/src/DotnetEventBus/Advanced/EventTransformer.cs b/src/DotnetEventBus/Advanced/EventTransformer.cs index 38e45af..dee5fee 100644 --- a/src/DotnetEventBus/Advanced/EventTransformer.cs +++ b/src/DotnetEventBus/Advanced/EventTransformer.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -15,7 +13,7 @@ namespace DotnetEventBus.Advanced; /// Supports fluent transformation chains and composition. /// Why: Allows handlers to receive events in a format optimized for their needs. /// -public sealed class EventTransformer where TSource : class where TTarget : class +public class EventTransformer where TSource : class where TTarget : class { private readonly Func _transformFunc; private readonly List> _postTransforms = []; @@ -78,7 +76,7 @@ public EventTransformer Chain( /// /// Builder for creating event transformers fluently. /// -public sealed class EventTransformerBuilder +public class EventTransformerBuilder { /// /// Creates a transformer from source to target type. @@ -104,7 +102,7 @@ public static EventTransformer CreatePropertyCopyTransformer p.Name == sourceProp.Name && p.CanWrite); - if (targetProp is not null) + if (targetProp != null) { try { diff --git a/src/DotnetEventBus/Advanced/MetricsCollector.cs b/src/DotnetEventBus/Advanced/MetricsCollector.cs index a896c1d..15f834f 100644 --- a/src/DotnetEventBus/Advanced/MetricsCollector.cs +++ b/src/DotnetEventBus/Advanced/MetricsCollector.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Advanced; /// Tracks timing, counts, errors, and throughput for observability. /// Why: Provides visibility into system health and performance bottlenecks. /// -public sealed class MetricsCollector +public class MetricsCollector { private readonly ConcurrentDictionary _metrics = []; private readonly ConcurrentDictionary _handlerMetrics = []; @@ -153,7 +151,7 @@ private void RecordHandlerFailure(string handlerName, string eventType) } } -public sealed class EventMetrics +public class EventMetrics { public string? EventType { get; set; } public long PublishCount { get; set; } @@ -170,7 +168,7 @@ public sealed class EventMetrics : 100; } -public sealed class HandlerMetrics +public class HandlerMetrics { public string? HandlerName { get; set; } public string? EventType { get; set; } @@ -184,7 +182,7 @@ public sealed class HandlerMetrics : 100; } -public sealed class SystemMetrics +public class SystemMetrics { public DateTime StartTime { get; set; } public TimeSpan UpTime { get; set; } diff --git a/src/DotnetEventBus/Advanced/RequestResponsePattern.cs b/src/DotnetEventBus/Advanced/RequestResponsePattern.cs index bd934b6..1ab2720 100644 --- a/src/DotnetEventBus/Advanced/RequestResponsePattern.cs +++ b/src/DotnetEventBus/Advanced/RequestResponsePattern.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Advanced; /// Allows handlers to return responses and clients to wait for replies. /// Why: Enables synchronous communication patterns while using an async event bus. /// -public sealed class RequestResponseBus +public class RequestResponseBus { private readonly ConcurrentDictionary> _pendingRequests = []; private readonly TimeSpan _defaultTimeout; @@ -163,7 +161,7 @@ public async Task ProcessRequestAsync(TRequest request, string requestId, Reques /// /// Request message for RPC-style calls. /// -public sealed class RequestMessage where T : class +public class RequestMessage where T : class { public string? RequestId { get; set; } public required T Payload { get; set; } @@ -175,7 +173,7 @@ public sealed class RequestMessage where T : class /// /// Response message for RPC-style calls. /// -public sealed class ResponseMessage where T : class +public class ResponseMessage where T : class { public string? RequestId { get; set; } public required T Payload { get; set; } diff --git a/src/DotnetEventBus/Advanced/SagaOrchestrator.cs b/src/DotnetEventBus/Advanced/SagaOrchestrator.cs index 3c94f1f..603a29f 100644 --- a/src/DotnetEventBus/Advanced/SagaOrchestrator.cs +++ b/src/DotnetEventBus/Advanced/SagaOrchestrator.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Advanced; /// Coordinates compensating transactions on failure for guaranteed consistency. /// Why: Critical for maintaining data consistency across microservices. /// -public sealed class SagaOrchestrator where TContext : class +public class SagaOrchestrator where TContext : class { private readonly List> _steps = []; private readonly string _sagaId; @@ -104,7 +102,7 @@ private async Task RollbackAsync(List> completedSteps, TConte // Execute compensations in reverse order foreach (var step in completedSteps.AsEnumerable().Reverse()) { - if (step.CompensationAction is not null) + if (step.CompensationAction != null) { try { @@ -130,7 +128,7 @@ public IEnumerable> GetStepStatus() } } -public sealed class SagaStep where T : class +public class SagaStep where T : class { public required string Name { get; set; } public required Func Action { get; set; } @@ -150,7 +148,7 @@ public enum SagaStepStatus CompensationFailed } -public sealed class SagaExecutionResult +public class SagaExecutionResult { public string? SagaId { get; set; } public bool Success { get; set; } diff --git a/src/DotnetEventBus/Api/EventBusApiController.cs b/src/DotnetEventBus/Api/EventBusApiController.cs index 2619b01..0961289 100644 --- a/src/DotnetEventBus/Api/EventBusApiController.cs +++ b/src/DotnetEventBus/Api/EventBusApiController.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -37,7 +35,7 @@ public virtual async Task> PublishEventAsync(str return ApiResponse.Error("Event type is required"); } - if (payload is null) + if (payload == null) { return ApiResponse.Error("Payload is required"); } @@ -67,7 +65,7 @@ public virtual async Task> PublishEventAsync(str /// public virtual async Task> PublishBatchAsync(List events) { - if (events is null || events.Count == 0) + if (events == null || events.Count == 0) { return ApiResponse.Error("At least one event is required"); } @@ -137,7 +135,7 @@ public virtual ApiResponse GetHealthAsync() /// /// Generic API response wrapper. /// -public sealed class ApiResponse +public class ApiResponse { public bool IsSuccess { get; set; } public T? Data { get; set; } @@ -166,7 +164,7 @@ public static ApiResponse Error(string error) /// /// Result of publishing an event. /// -public sealed class EventPublishResult +public class EventPublishResult { public string? EventId { get; set; } public string? EventType { get; set; } @@ -177,7 +175,7 @@ public sealed class EventPublishResult /// /// Result of publishing a batch. /// -public sealed class BatchPublishResult +public class BatchPublishResult { public string? BatchId { get; set; } public int EventCount { get; set; } @@ -188,7 +186,7 @@ public sealed class BatchPublishResult /// /// Event bus statistics for API responses. /// -public sealed class EventBusStats +public class EventBusStats { public string? Status { get; set; } public long TotalEventsPublished { get; set; } diff --git a/src/DotnetEventBus/Caching/IEventCache.cs b/src/DotnetEventBus/Caching/IEventCache.cs index 78eefcd..b7ef869 100644 --- a/src/DotnetEventBus/Caching/IEventCache.cs +++ b/src/DotnetEventBus/Caching/IEventCache.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -61,7 +59,7 @@ public interface IEventCache /// /// Statistics about cache performance. /// -public sealed class CacheStats +public class CacheStats { public long Hits { get; set; } public long Misses { get; set; } diff --git a/src/DotnetEventBus/Caching/InMemoryEventCache.cs b/src/DotnetEventBus/Caching/InMemoryEventCache.cs index b1274f6..58ced3a 100644 --- a/src/DotnetEventBus/Caching/InMemoryEventCache.cs +++ b/src/DotnetEventBus/Caching/InMemoryEventCache.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Caching; /// Uses concurrent dictionary for thread-safe access and automatic expiration. /// Why: Provides fast, local caching without external dependencies for single-instance deployments. /// -public sealed class InMemoryEventCache : IEventCache +public class InMemoryEventCache : IEventCache { private readonly ConcurrentDictionary _cache = []; private readonly object _statsLock = new(); diff --git a/src/DotnetEventBus/Cli/CommandLineInterface.cs b/src/DotnetEventBus/Cli/CommandLineInterface.cs index ccbf141..6361923 100644 --- a/src/DotnetEventBus/Cli/CommandLineInterface.cs +++ b/src/DotnetEventBus/Cli/CommandLineInterface.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Cli; /// Provides commands for publishing, subscribing, querying, and managing events. /// Why: Enables system operators to interact with the event bus without code. /// -public sealed class CommandLineInterface +public class CommandLineInterface { private readonly Dictionary _commands = []; private readonly StringBuilder _helpText = new(); @@ -132,7 +130,7 @@ public interface ICommand /// /// Result of command execution. /// -public sealed class CommandResult +public class CommandResult { public bool Success { get; } public string Message { get; } diff --git a/src/DotnetEventBus/Cli/PublishCommand.cs b/src/DotnetEventBus/Cli/PublishCommand.cs index 7089111..f8b0568 100644 --- a/src/DotnetEventBus/Cli/PublishCommand.cs +++ b/src/DotnetEventBus/Cli/PublishCommand.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Cli; /// CLI command for publishing events. /// Supports JSON payload and metadata options. /// -public sealed class PublishCommand : ICommand +public class PublishCommand : ICommand { public string Name => "publish"; public string Description => "Publish an event to the event bus"; diff --git a/src/DotnetEventBus/Cli/QueryCommand.cs b/src/DotnetEventBus/Cli/QueryCommand.cs index e8aeb7d..8d5ca36 100644 --- a/src/DotnetEventBus/Cli/QueryCommand.cs +++ b/src/DotnetEventBus/Cli/QueryCommand.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -16,7 +14,7 @@ namespace DotnetEventBus.Cli; /// CLI command for querying events and their history. /// Supports filtering by event type and time range. /// -public sealed class QueryCommand : ICommand +public class QueryCommand : ICommand { public string Name => "query"; public string Description => "Query events and event history"; diff --git a/src/DotnetEventBus/Cli/StatsCommand.cs b/src/DotnetEventBus/Cli/StatsCommand.cs index 565853d..d11f106 100644 --- a/src/DotnetEventBus/Cli/StatsCommand.cs +++ b/src/DotnetEventBus/Cli/StatsCommand.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -15,7 +13,7 @@ namespace DotnetEventBus.Cli; /// CLI command for viewing system statistics and health. /// Displays metrics about event processing and system status. /// -public sealed class StatsCommand : ICommand +public class StatsCommand : ICommand { public string Name => "stats"; public string Description => "Display event bus statistics and metrics"; diff --git a/src/DotnetEventBus/Cli/SubscribeCommand.cs b/src/DotnetEventBus/Cli/SubscribeCommand.cs index 2f49f71..e5c1326 100644 --- a/src/DotnetEventBus/Cli/SubscribeCommand.cs +++ b/src/DotnetEventBus/Cli/SubscribeCommand.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Cli; /// CLI command for managing event subscriptions. /// Allows creating, listing, and removing subscriptions. /// -public sealed class SubscribeCommand : ICommand +public class SubscribeCommand : ICommand { public string Name => "subscribe"; public string Description => "Manage event subscriptions"; diff --git a/src/DotnetEventBus/Configuration/EventBusOptions.cs b/src/DotnetEventBus/Configuration/EventBusOptions.cs index 231ea7b..f99b409 100644 --- a/src/DotnetEventBus/Configuration/EventBusOptions.cs +++ b/src/DotnetEventBus/Configuration/EventBusOptions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -10,7 +8,7 @@ namespace DotnetEventBus.Configuration; /// /// Configuration options for the event bus. /// -public sealed class EventBusOptions +public class EventBusOptions { /// /// Default timeout for synchronous handler execution. diff --git a/src/DotnetEventBus/Configuration/EventRoutingConfiguration.cs b/src/DotnetEventBus/Configuration/EventRoutingConfiguration.cs index eda570a..b3fe523 100644 --- a/src/DotnetEventBus/Configuration/EventRoutingConfiguration.cs +++ b/src/DotnetEventBus/Configuration/EventRoutingConfiguration.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -16,7 +14,7 @@ namespace DotnetEventBus.Configuration; /// Allows events to be routed to different handlers based on content or metadata. /// Why: Enables sophisticated event routing without handler modifications. /// -public sealed class EventRoutingConfiguration +public class EventRoutingConfiguration { private readonly Dictionary> _routes = []; @@ -59,11 +57,11 @@ public bool ShouldRoute(string eventType, string handlerName, Dictionary r.TargetHandler == handlerName); - if (targetRoute is null) + if (targetRoute == null) return false; // Check route conditions - if (targetRoute.Condition is not null && metadata is not null) + if (targetRoute.Condition != null && metadata != null) { return targetRoute.Condition(metadata); } @@ -91,7 +89,7 @@ public void Clear() /// /// Represents a routing rule for event delivery. /// -public sealed class RoutingRule +public class RoutingRule { /// /// The target handler name. @@ -117,7 +115,7 @@ public sealed class RoutingRule /// /// Fluent builder for event routing configuration. /// -public sealed class EventRoutingBuilder +public class EventRoutingBuilder { private readonly EventRoutingConfiguration _configuration = new(); diff --git a/src/DotnetEventBus/Configuration/MiddlewareConfiguration.cs b/src/DotnetEventBus/Configuration/MiddlewareConfiguration.cs index 374ccea..5db8c0b 100644 --- a/src/DotnetEventBus/Configuration/MiddlewareConfiguration.cs +++ b/src/DotnetEventBus/Configuration/MiddlewareConfiguration.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -13,7 +11,7 @@ namespace DotnetEventBus.Configuration; /// Configuration options for middleware components. /// Centralizes all middleware settings in one place. /// -public sealed class MiddlewareConfiguration +public class MiddlewareConfiguration { /// /// Logging configuration. @@ -39,7 +37,7 @@ public sealed class MiddlewareConfiguration /// /// Logging middleware configuration. /// -public sealed class LoggingOptions +public class LoggingOptions { /// /// Whether to log event payloads. @@ -70,7 +68,7 @@ public sealed class LoggingOptions /// /// Error handling middleware configuration. /// -public sealed class ErrorHandlingOptions +public class ErrorHandlingOptions { /// /// Maximum number of retry attempts. @@ -106,7 +104,7 @@ public sealed class ErrorHandlingOptions /// /// Rate limiting middleware configuration. /// -public sealed class RateLimitingOptions +public class RateLimitingOptions { /// /// Whether to enable rate limiting. @@ -137,7 +135,7 @@ public sealed class RateLimitingOptions /// /// Caching configuration. /// -public sealed class CachingOptions +public class CachingOptions { /// /// Whether to enable caching. diff --git a/src/DotnetEventBus/Configuration/PipelineBuilderExtensions.cs b/src/DotnetEventBus/Configuration/PipelineBuilderExtensions.cs index c316ff9..9c237bd 100644 --- a/src/DotnetEventBus/Configuration/PipelineBuilderExtensions.cs +++ b/src/DotnetEventBus/Configuration/PipelineBuilderExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Configuration/ServiceCollectionExtensions.cs b/src/DotnetEventBus/Configuration/ServiceCollectionExtensions.cs index 9aeccea..e239c87 100644 --- a/src/DotnetEventBus/Configuration/ServiceCollectionExtensions.cs +++ b/src/DotnetEventBus/Configuration/ServiceCollectionExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -23,7 +21,7 @@ public static IServiceCollection AddEventBus( this IServiceCollection services, Action? configureOptions = null) { - if (services is null) + if (services == null) throw new ArgumentNullException(nameof(services)); var options = new EventBusOptions(); @@ -52,13 +50,13 @@ public static IServiceCollection AddEventBus( IDeadLetterRepository deadLetterRepository, Action? configureOptions = null) { - if (services is null) + if (services == null) throw new ArgumentNullException(nameof(services)); - if (messageRepository is null) + if (messageRepository == null) throw new ArgumentNullException(nameof(messageRepository)); - if (subscriptionRepository is null) + if (subscriptionRepository == null) throw new ArgumentNullException(nameof(subscriptionRepository)); - if (deadLetterRepository is null) + if (deadLetterRepository == null) throw new ArgumentNullException(nameof(deadLetterRepository)); var options = new EventBusOptions(); diff --git a/src/DotnetEventBus/Constants.cs b/src/DotnetEventBus/Constants.cs index b8f7e05..b7725cf 100644 --- a/src/DotnetEventBus/Constants.cs +++ b/src/DotnetEventBus/Constants.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/DotnetEventBus.csproj b/src/DotnetEventBus/DotnetEventBus.csproj index e1a4209..042231a 100644 --- a/src/DotnetEventBus/DotnetEventBus.csproj +++ b/src/DotnetEventBus/DotnetEventBus.csproj @@ -8,7 +8,7 @@ DotnetEventBus DotnetEventBus Zaiets.dotnet.event.bus - 2.0.2 + 2.0.0 Vladyslav Zaiets In-process and distributed event bus for .NET - pub/sub, request/reply, dead letter, polymorphic handlers event-bus pub-sub dead-letter cqrs mediator event-sourcing diff --git a/src/DotnetEventBus/EventBusBuilder.cs b/src/DotnetEventBus/EventBusBuilder.cs index 8cb2163..be9dd9e 100644 --- a/src/DotnetEventBus/EventBusBuilder.cs +++ b/src/DotnetEventBus/EventBusBuilder.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -15,7 +13,7 @@ namespace DotnetEventBus; /// /// Fluent builder for configuring and creating the event bus. /// -public sealed class EventBusBuilder +public class EventBusBuilder { private EventBusOptions _options = new(); private IEventMessageRepository? _messageRepository; @@ -36,7 +34,7 @@ public EventBusBuilder(IServiceCollection services) /// public EventBusBuilder WithOptions(Action configureOptions) { - if (configureOptions is null) + if (configureOptions == null) throw new ArgumentNullException(nameof(configureOptions)); configureOptions(_options); @@ -154,7 +152,7 @@ public IServiceCollection Build() { _options.Validate(); - if (_messageRepository is not null || _subscriptionRepository is not null || _deadLetterRepository is not null) + if (_messageRepository != null || _subscriptionRepository != null || _deadLetterRepository != null) { _messageRepository ??= new InMemoryEventMessageRepository(); _subscriptionRepository ??= new InMemorySubscriptionRepository(); @@ -213,7 +211,7 @@ public static class EventBusBuilderExtensions /// public static EventBusBuilder AddEventBusBuilder(this IServiceCollection services) { - if (services is null) + if (services == null) throw new ArgumentNullException(nameof(services)); return new EventBusBuilder(services); diff --git a/src/DotnetEventBus/Exceptions/EventBusException.cs b/src/DotnetEventBus/Exceptions/EventBusException.cs index be8e17c..787d268 100644 --- a/src/DotnetEventBus/Exceptions/EventBusException.cs +++ b/src/DotnetEventBus/Exceptions/EventBusException.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -10,7 +8,7 @@ namespace DotnetEventBus.Exceptions; /// /// Base exception for all event bus related errors. /// -public sealed class EventBusException : Exception +public class EventBusException : Exception { /// /// Initializes a new instance of the class. @@ -32,7 +30,7 @@ public EventBusException(string? message, Exception? innerException) /// /// Thrown when no handlers are registered for a given event type. /// -public sealed class NoHandlersRegisteredException : EventBusException +public class NoHandlersRegisteredException : EventBusException { public string EventType { get; } @@ -46,7 +44,7 @@ public NoHandlersRegisteredException(string eventType) /// /// Thrown when an event handler invocation fails. /// -public sealed class HandlerInvocationException : EventBusException +public class HandlerInvocationException : EventBusException { public string HandlerName { get; } public string EventType { get; } @@ -62,7 +60,7 @@ public HandlerInvocationException(string handlerName, string eventType, Exceptio /// /// Thrown when attempting to subscribe with an invalid handler. /// -public sealed class InvalidHandlerException : EventBusException +public class InvalidHandlerException : EventBusException { public Type HandlerType { get; } @@ -76,7 +74,7 @@ public InvalidHandlerException(Type handlerType) /// /// Thrown when message serialization or deserialization fails. /// -public sealed class MessageSerializationException : EventBusException +public class MessageSerializationException : EventBusException { public string MessageType { get; } @@ -90,7 +88,7 @@ public MessageSerializationException(string messageType, Exception? innerExcepti /// /// Thrown when attempting to access a distributed event bus without proper configuration. /// -public sealed class DistributedBusNotConfiguredException : EventBusException +public class DistributedBusNotConfiguredException : EventBusException { public DistributedBusNotConfiguredException() : base("Distributed event bus is not properly configured. Ensure transport is registered.") @@ -101,7 +99,7 @@ public DistributedBusNotConfiguredException() /// /// Thrown when a request times out waiting for a reply. /// -public sealed class RequestTimeoutException : EventBusException +public class RequestTimeoutException : EventBusException { public string RequestType { get; } public TimeSpan Timeout { get; } diff --git a/src/DotnetEventBus/Formatters/CsvEventFormatter.cs b/src/DotnetEventBus/Formatters/CsvEventFormatter.cs index 1433e7f..589dd81 100644 --- a/src/DotnetEventBus/Formatters/CsvEventFormatter.cs +++ b/src/DotnetEventBus/Formatters/CsvEventFormatter.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Formatters; /// Automatically extracts properties from event objects. /// Why: CSV is a standard format for bulk event export and analysis in external tools. /// -public sealed class CsvEventFormatter : IEventFormatter +public class CsvEventFormatter : IEventFormatter { public string Format => "csv"; public string ContentType => "text/csv"; diff --git a/src/DotnetEventBus/Formatters/EventFormatterFactory.cs b/src/DotnetEventBus/Formatters/EventFormatterFactory.cs index 17d5c80..fe53981 100644 --- a/src/DotnetEventBus/Formatters/EventFormatterFactory.cs +++ b/src/DotnetEventBus/Formatters/EventFormatterFactory.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -16,7 +14,7 @@ namespace DotnetEventBus.Formatters; /// Provides a registry of formatters and format negotiation by MIME type. /// Why: Allows flexible switching between output formats without changing client code. /// -public sealed class EventFormatterFactory +public class EventFormatterFactory { private readonly Dictionary _formatters = []; @@ -67,7 +65,7 @@ public void Register(IEventFormatter formatter) var formatter = _formatters.Values.FirstOrDefault(f => f.ContentType.Equals(contentType, StringComparison.OrdinalIgnoreCase)); - if (formatter is not null) + if (formatter != null) return formatter; // Partial match (e.g., "application/json" matches "json") diff --git a/src/DotnetEventBus/Formatters/IEventFormatter.cs b/src/DotnetEventBus/Formatters/IEventFormatter.cs index 3832543..ee379b3 100644 --- a/src/DotnetEventBus/Formatters/IEventFormatter.cs +++ b/src/DotnetEventBus/Formatters/IEventFormatter.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Formatters/JsonEventFormatter.cs b/src/DotnetEventBus/Formatters/JsonEventFormatter.cs index 39e1bc3..14b163b 100644 --- a/src/DotnetEventBus/Formatters/JsonEventFormatter.cs +++ b/src/DotnetEventBus/Formatters/JsonEventFormatter.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -16,7 +14,7 @@ namespace DotnetEventBus.Formatters; /// Provides both compact and pretty-printed output options. /// Why: JSON is the standard format for distributed event systems and REST APIs. /// -public sealed class JsonEventFormatter : IEventFormatter +public class JsonEventFormatter : IEventFormatter { private readonly JsonSerializerOptions _compactOptions; private readonly JsonSerializerOptions _prettyOptions; @@ -69,7 +67,7 @@ public string Serialize(object data, bool prettyPrint = false) public string FormatEvent(object eventData, bool includePrettyPrint = false) { - if (eventData is null) + if (eventData == null) return "null"; return Serialize(eventData, includePrettyPrint); diff --git a/src/DotnetEventBus/Formatters/XmlEventFormatter.cs b/src/DotnetEventBus/Formatters/XmlEventFormatter.cs index 724917a..9c894af 100644 --- a/src/DotnetEventBus/Formatters/XmlEventFormatter.cs +++ b/src/DotnetEventBus/Formatters/XmlEventFormatter.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Formatters; /// Supports both serialization and deserialization with proper formatting. /// Why: XML is required for integration with legacy enterprise systems. /// -public sealed class XmlEventFormatter : IEventFormatter +public class XmlEventFormatter : IEventFormatter { public string Format => "xml"; public string ContentType => "application/xml"; diff --git a/src/DotnetEventBus/Handlers/HandlerBase.cs b/src/DotnetEventBus/Handlers/HandlerBase.cs index 1d266fa..63c240e 100644 --- a/src/DotnetEventBus/Handlers/HandlerBase.cs +++ b/src/DotnetEventBus/Handlers/HandlerBase.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -162,7 +160,7 @@ public virtual bool CanHandle(Type eventType) /// protected void RegisterHandledType(Type eventType) { - if (eventType is null) + if (eventType == null) throw new ArgumentNullException(nameof(eventType)); SupportedTypes.Add(eventType); diff --git a/src/DotnetEventBus/Handlers/IEventHandler.cs b/src/DotnetEventBus/Handlers/IEventHandler.cs index 278ae8c..2f5e72a 100644 --- a/src/DotnetEventBus/Handlers/IEventHandler.cs +++ b/src/DotnetEventBus/Handlers/IEventHandler.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Handlers/PredicateFilteredHandler.cs b/src/DotnetEventBus/Handlers/PredicateFilteredHandler.cs index ee0e5bc..10eb433 100644 --- a/src/DotnetEventBus/Handlers/PredicateFilteredHandler.cs +++ b/src/DotnetEventBus/Handlers/PredicateFilteredHandler.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Handlers/PredicateSubscriptionBuilder.cs b/src/DotnetEventBus/Handlers/PredicateSubscriptionBuilder.cs index f8e71df..e1c7217 100644 --- a/src/DotnetEventBus/Handlers/PredicateSubscriptionBuilder.cs +++ b/src/DotnetEventBus/Handlers/PredicateSubscriptionBuilder.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -159,7 +157,7 @@ public PredicateSubscriptionBuilder WithLogger(ILogger logger) /// public IDisposable Register() { - if (_asyncHandler is null) + if (_asyncHandler == null) throw new InvalidOperationException( $"No handler configured. Call {nameof(WithHandler)} before calling {nameof(Register)}."); diff --git a/src/DotnetEventBus/Integration/CircuitBreaker.cs b/src/DotnetEventBus/Integration/CircuitBreaker.cs index 3faebb7..ff439a0 100644 --- a/src/DotnetEventBus/Integration/CircuitBreaker.cs +++ b/src/DotnetEventBus/Integration/CircuitBreaker.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -16,7 +14,7 @@ namespace DotnetEventBus.Integration; /// Stops hammering failing endpoints and allows them time to recover. /// Why: Prevents cascading failures and improves overall system stability. /// -public sealed class CircuitBreaker +public class CircuitBreaker { private CircuitBreakerState _state = CircuitBreakerState.Closed; private int _failureCount = 0; @@ -170,7 +168,7 @@ public enum CircuitBreakerState HalfOpen // Testing if service recovered } -public sealed class CircuitBreakerOpenException : Exception +public class CircuitBreakerOpenException : Exception { public CircuitBreakerOpenException(string message) : base(message) { } } diff --git a/src/DotnetEventBus/Integration/HttpEventPublisher.cs b/src/DotnetEventBus/Integration/HttpEventPublisher.cs index 6cea8bb..0f0f362 100644 --- a/src/DotnetEventBus/Integration/HttpEventPublisher.cs +++ b/src/DotnetEventBus/Integration/HttpEventPublisher.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -19,7 +17,7 @@ namespace DotnetEventBus.Integration; /// Supports retry logic, timeouts, and header customization. /// Why: Enables integration with external services and microservices over HTTP. /// -public sealed class HttpEventPublisher +public class HttpEventPublisher { private readonly HttpClient _httpClient; private readonly ILogger _logger; @@ -58,7 +56,7 @@ public async Task PublishAsync( contentType ?? "application/json"); // Add custom headers - if (customHeaders is not null) + if (customHeaders != null) { foreach (var header in customHeaders) { @@ -122,7 +120,7 @@ private bool ShouldRetry(int statusCode) } } -public sealed class HttpEventPublisherOptions +public class HttpEventPublisherOptions { public int MaxRetries { get; set; } = 3; public int RetryDelayMs { get; set; } = 1000; @@ -130,7 +128,7 @@ public sealed class HttpEventPublisherOptions public string? CorrelationIdHeaderName { get; set; } = "X-Correlation-Id"; } -public sealed class HttpPublishResult +public class HttpPublishResult { public bool Success { get; } public int StatusCode { get; } diff --git a/src/DotnetEventBus/Integration/RetryPolicy.cs b/src/DotnetEventBus/Integration/RetryPolicy.cs index 1b73eea..9ebe4a2 100644 --- a/src/DotnetEventBus/Integration/RetryPolicy.cs +++ b/src/DotnetEventBus/Integration/RetryPolicy.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Integration; /// Supports exponential backoff, jitter, and custom retry conditions. /// Why: Handles transient failures gracefully without losing events. /// -public sealed class RetryPolicy +public class RetryPolicy { private int _maxRetries = 3; private TimeSpan _initialDelay = TimeSpan.FromSeconds(1); @@ -182,7 +180,7 @@ private TimeSpan CalculateDelay(int attemptNumber) private bool IsRetryable(Exception ex) { // Use custom filter if provided - if (_retryableExceptionFilter is not null) + if (_retryableExceptionFilter != null) { return _retryableExceptionFilter(ex); } diff --git a/src/DotnetEventBus/Integration/WebhookHandler.cs b/src/DotnetEventBus/Integration/WebhookHandler.cs index f9abf68..1a72c5c 100644 --- a/src/DotnetEventBus/Integration/WebhookHandler.cs +++ b/src/DotnetEventBus/Integration/WebhookHandler.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Integration; /// Provides signature verification for security and filtering capabilities. /// Why: Webhooks allow external systems to react to events in near real-time. /// -public sealed class WebhookHandler +public class WebhookHandler { private readonly List _subscriptions = []; private readonly string? _signingSecret; @@ -45,7 +43,7 @@ public void Subscribe(WebhookSubscription subscription) public bool Unsubscribe(string subscriptionId) { var subscription = _subscriptions.FirstOrDefault(s => s.Id == subscriptionId); - if (subscription is null) + if (subscription == null) return false; _subscriptions.Remove(subscription); @@ -105,7 +103,7 @@ public IEnumerable GetAllSubscriptions() public bool UpdateSubscription(string subscriptionId, Action updates) { var subscription = _subscriptions.FirstOrDefault(s => s.Id == subscriptionId); - if (subscription is null) + if (subscription == null) return false; updates(subscription); @@ -116,7 +114,7 @@ public bool UpdateSubscription(string subscriptionId, Action /// Represents a webhook subscription for event delivery. /// -public sealed class WebhookSubscription +public class WebhookSubscription { public string? Id { get; set; } public required string Url { get; set; } diff --git a/src/DotnetEventBus/Middleware/ErrorHandlingMiddleware.cs b/src/DotnetEventBus/Middleware/ErrorHandlingMiddleware.cs index 0374cc6..73fe870 100644 --- a/src/DotnetEventBus/Middleware/ErrorHandlingMiddleware.cs +++ b/src/DotnetEventBus/Middleware/ErrorHandlingMiddleware.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -16,7 +14,7 @@ namespace DotnetEventBus.Middleware; /// Provides centralized exception handling, recovery, and dead-letter routing. /// Why: Prevents cascading failures and ensures failed events are captured for analysis. /// -public sealed class ErrorHandlingMiddleware +public class ErrorHandlingMiddleware { private readonly ILogger _logger; private readonly int _maxRetries; @@ -69,7 +67,7 @@ public EventBusMiddleware Create() } // All retries exhausted - invoke custom error handler if provided - if (_errorHandler is not null && lastException is not null) + if (_errorHandler != null && lastException != null) { bool handled = await _errorHandler(context, lastException); if (handled) @@ -82,7 +80,7 @@ public EventBusMiddleware Create() // Could not recover - rethrow or mark as failed context.IsProcessed = false; - if (lastException is not null) + if (lastException != null) { throw new EventProcessingException( $"Event {context.EventType} failed after {_maxRetries} retries", @@ -95,7 +93,7 @@ public EventBusMiddleware Create() /// /// Exception thrown when event processing fails after all retry attempts. /// -public sealed class EventProcessingException : Exception +public class EventProcessingException : Exception { public EventProcessingException(string message, Exception? innerException = null) : base(message, innerException) diff --git a/src/DotnetEventBus/Middleware/EventBusLoggingMiddleware.cs b/src/DotnetEventBus/Middleware/EventBusLoggingMiddleware.cs index 0f43ab5..b2f9d05 100644 --- a/src/DotnetEventBus/Middleware/EventBusLoggingMiddleware.cs +++ b/src/DotnetEventBus/Middleware/EventBusLoggingMiddleware.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -18,7 +16,7 @@ namespace DotnetEventBus.Middleware; /// Tracks timing, event data, and execution results for observability. /// Why: Essential for debugging and monitoring event flow in production systems. /// -public sealed class EventBusLoggingMiddleware +public class EventBusLoggingMiddleware { private readonly ILogger _logger; private readonly LogLevel _logLevel; @@ -49,7 +47,7 @@ public EventBusMiddleware Create() "Event published: {EventType} [CorrelationId: {CorrelationId}]", context.EventType, correlationId); - if (_logEventPayload && context.EventData is not null) + if (_logEventPayload && context.EventData != null) { var payload = JsonSerializer.Serialize(context.EventData, new JsonSerializerOptions { WriteIndented = false }); _logger.Log(_logLevel, "Event payload: {Payload}", payload); diff --git a/src/DotnetEventBus/Middleware/PipelineBuilder.cs b/src/DotnetEventBus/Middleware/PipelineBuilder.cs index 82d657e..f4ec2bf 100644 --- a/src/DotnetEventBus/Middleware/PipelineBuilder.cs +++ b/src/DotnetEventBus/Middleware/PipelineBuilder.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -14,7 +12,7 @@ namespace DotnetEventBus.Middleware; /// Builds and manages the middleware pipeline for event processing. /// Uses a chain-of-responsibility pattern to compose middleware components. /// -public sealed class PipelineBuilder +public class PipelineBuilder { private readonly List> _middlewares = []; @@ -69,7 +67,7 @@ public EventBusMiddleware Build() /// Context passed through the middleware pipeline. /// Contains the event data and metadata for processing. /// -public sealed class EventContext +public class EventContext { public required string EventType { get; set; } public required object EventData { get; set; } diff --git a/src/DotnetEventBus/Middleware/RateLimitingMiddleware.cs b/src/DotnetEventBus/Middleware/RateLimitingMiddleware.cs index fe779de..177796d 100644 --- a/src/DotnetEventBus/Middleware/RateLimitingMiddleware.cs +++ b/src/DotnetEventBus/Middleware/RateLimitingMiddleware.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -20,7 +18,7 @@ namespace DotnetEventBus.Middleware; /// Uses a sliding window algorithm to track request rates per event type. /// Why: Prevents system overload and ensures fair resource distribution across event types. /// -public sealed class RateLimitingMiddleware +public class RateLimitingMiddleware { private readonly ILogger _logger; private readonly Dictionary _buckets = []; @@ -126,7 +124,7 @@ public void RecordRequest() } } -public sealed class RateLimitExceededException : Exception +public class RateLimitExceededException : Exception { public RateLimitExceededException(string message) : base(message) { } } diff --git a/src/DotnetEventBus/Models/DeadLetterEntry.cs b/src/DotnetEventBus/Models/DeadLetterEntry.cs index 030442b..6351531 100644 --- a/src/DotnetEventBus/Models/DeadLetterEntry.cs +++ b/src/DotnetEventBus/Models/DeadLetterEntry.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -10,7 +8,7 @@ namespace DotnetEventBus.Models; /// /// Represents a message that failed processing and was moved to the dead letter queue. /// -public sealed class DeadLetterEntry +public class DeadLetterEntry { /// /// Unique identifier for this dead letter entry. @@ -70,9 +68,7 @@ public DeadLetterEntry( Message = message ?? throw new ArgumentNullException(nameof(message)); FailedHandlerName = failedHandlerName ?? throw new ArgumentNullException(nameof(failedHandlerName)); ExceptionMessage = exception?.Message ?? "Unknown exception"; - // Hotfix: Capture full exception details including stack trace and inner exceptions - // using ToString() instead of just StackTrace property to preserve complete exception chain - ExceptionStackTrace = exception?.ToString(); + ExceptionStackTrace = exception?.StackTrace; CreatedAtUtc = DateTime.UtcNow; MaxRetryAttempts = maxRetryAttempts; Status = DeadLetterStatus.Pending; diff --git a/src/DotnetEventBus/Models/EventEnvelope.cs b/src/DotnetEventBus/Models/EventEnvelope.cs index 74abbf6..b576e34 100644 --- a/src/DotnetEventBus/Models/EventEnvelope.cs +++ b/src/DotnetEventBus/Models/EventEnvelope.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -15,7 +13,7 @@ namespace DotnetEventBus.Models; /// Used for serialization, transmission, and audit trail. /// Why: Decouples event payload from infrastructure concerns. /// -public sealed class EventEnvelope +public class EventEnvelope { /// /// Unique identifier for this event. @@ -156,14 +154,14 @@ public Dictionary GetHeaders() /// public bool IsValid() { - return !string.IsNullOrEmpty(EventType) && Payload is not null; + return !string.IsNullOrEmpty(EventType) && Payload != null; } } /// /// Represents the result of event processing. /// -public sealed class EventProcessingResult +public class EventProcessingResult { public bool Success { get; set; } public string? EventId { get; set; } @@ -177,7 +175,7 @@ public sealed class EventProcessingResult /// /// Batch of events to be processed together. /// -public sealed class EventBatch +public class EventBatch { public string? BatchId { get; set; } = Guid.NewGuid().ToString(); public List Events { get; set; } = []; diff --git a/src/DotnetEventBus/Models/EventMessage.cs b/src/DotnetEventBus/Models/EventMessage.cs index 6fb5a8d..3ff43ae 100644 --- a/src/DotnetEventBus/Models/EventMessage.cs +++ b/src/DotnetEventBus/Models/EventMessage.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -10,7 +8,7 @@ namespace DotnetEventBus.Models; /// /// Represents a message published to the event bus. /// -public sealed class EventMessage +public class EventMessage { /// /// Unique identifier for this message (alias for MessageId, required by repository infrastructure). diff --git a/src/DotnetEventBus/Models/PublishResult.cs b/src/DotnetEventBus/Models/PublishResult.cs index 4b2d2d6..b315aa4 100644 --- a/src/DotnetEventBus/Models/PublishResult.cs +++ b/src/DotnetEventBus/Models/PublishResult.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -10,7 +8,7 @@ namespace DotnetEventBus.Models; /// /// Represents the result of publishing an event to the event bus. /// -public sealed class PublishResult +public class PublishResult { /// /// The message ID of the published event. @@ -94,7 +92,7 @@ public void AddFailedHandler(string handlerName, Exception exception) FailedHandlerNames.Add(handlerName); FailedHandlers++; - if (Exception is null) + if (Exception == null) { Exception = exception; ErrorMessage = exception?.Message; diff --git a/src/DotnetEventBus/Models/Subscription.cs b/src/DotnetEventBus/Models/Subscription.cs index b91bc62..ec9c9bd 100644 --- a/src/DotnetEventBus/Models/Subscription.cs +++ b/src/DotnetEventBus/Models/Subscription.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -10,7 +8,7 @@ namespace DotnetEventBus.Models; /// /// Represents a subscription between an event type and its handlers. /// -public sealed class Subscription +public class Subscription { /// /// Unique identifier for this subscription. diff --git a/src/DotnetEventBus/Monitoring/HealthCheck.cs b/src/DotnetEventBus/Monitoring/HealthCheck.cs index e48b335..58a27c4 100644 --- a/src/DotnetEventBus/Monitoring/HealthCheck.cs +++ b/src/DotnetEventBus/Monitoring/HealthCheck.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -16,7 +14,7 @@ namespace DotnetEventBus.Monitoring; /// Performs periodic checks on critical components and reports status. /// Why: Enables automated detection of system degradation and failures. /// -public sealed class HealthCheck +public class HealthCheck { private readonly Dictionary _probes = []; private HealthStatus _lastStatus = HealthStatus.Unknown; @@ -96,7 +94,7 @@ public interface IHealthCheckProbe /// /// Result of a single health check probe. /// -public sealed class ProbeResult +public class ProbeResult { public HealthStatus Status { get; set; } public string? Message { get; set; } @@ -106,7 +104,7 @@ public sealed class ProbeResult /// /// Result of the overall health check. /// -public sealed class HealthCheckResult +public class HealthCheckResult { public HealthStatus OverallStatus { get; set; } public DateTime CheckedAt { get; set; } diff --git a/src/DotnetEventBus/Performance/PerformanceProfiler.cs b/src/DotnetEventBus/Performance/PerformanceProfiler.cs index 6657b69..c77e6ae 100644 --- a/src/DotnetEventBus/Performance/PerformanceProfiler.cs +++ b/src/DotnetEventBus/Performance/PerformanceProfiler.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Performance; /// Helps identify bottlenecks and optimize event processing. /// Why: Data-driven optimization requires accurate performance measurements. /// -public sealed class PerformanceProfiler +public class PerformanceProfiler { private readonly Dictionary> _timings = []; private readonly Stopwatch _sessionStopwatch = Stopwatch.StartNew(); @@ -110,7 +108,7 @@ public void Profile(string operationName, Action operation) /// public IEnumerable GetAllStats() { - return _timings.Keys.Select(op => GetStats(op)).Where(s => s is not null)!; + return _timings.Keys.Select(op => GetStats(op)).Where(s => s != null)!; } /// @@ -211,7 +209,7 @@ private static double GetPercentile(List values, int percentile) } } -public sealed class OperationStats +public class OperationStats { public string? OperationName { get; set; } public int ExecutionCount { get; set; } @@ -224,7 +222,7 @@ public sealed class OperationStats public double P99TimeMs { get; set; } } -public sealed class ProfilingSessionSummary +public class ProfilingSessionSummary { public TimeSpan SessionDuration { get; set; } public int OperationCount { get; set; } diff --git a/src/DotnetEventBus/Repositories/DeadLetterRepository.cs b/src/DotnetEventBus/Repositories/DeadLetterRepository.cs index b5337ba..0e3ac5e 100644 --- a/src/DotnetEventBus/Repositories/DeadLetterRepository.cs +++ b/src/DotnetEventBus/Repositories/DeadLetterRepository.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -56,7 +54,7 @@ Task> GetByTimeRangeAsync( /// /// In-memory implementation of the dead letter repository. /// -public sealed class InMemoryDeadLetterRepository : InMemoryRepository, IDeadLetterRepository +public class InMemoryDeadLetterRepository : InMemoryRepository, IDeadLetterRepository { public async Task> GetPendingAsync(CancellationToken cancellationToken = default) { diff --git a/src/DotnetEventBus/Repositories/EventMessageRepository.cs b/src/DotnetEventBus/Repositories/EventMessageRepository.cs index 005dd63..97d6940 100644 --- a/src/DotnetEventBus/Repositories/EventMessageRepository.cs +++ b/src/DotnetEventBus/Repositories/EventMessageRepository.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -51,7 +49,7 @@ Task> GetByTimeRangeAsync( /// /// In-memory implementation of the event message repository. /// -public sealed class InMemoryEventMessageRepository : InMemoryRepository, IEventMessageRepository +public class InMemoryEventMessageRepository : InMemoryRepository, IEventMessageRepository { public async Task> GetByEventTypeAsync(string eventType, CancellationToken cancellationToken = default) { diff --git a/src/DotnetEventBus/Repositories/IRepository.cs b/src/DotnetEventBus/Repositories/IRepository.cs index 49b1575..b507798 100644 --- a/src/DotnetEventBus/Repositories/IRepository.cs +++ b/src/DotnetEventBus/Repositories/IRepository.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -66,7 +64,7 @@ public interface IRepository where T : class /// /// Result of a paginated query. /// -public sealed class PaginatedResult where T : class +public class PaginatedResult where T : class { public List Items { get; set; } = new(); public int PageNumber { get; set; } diff --git a/src/DotnetEventBus/Repositories/InMemoryRepository.cs b/src/DotnetEventBus/Repositories/InMemoryRepository.cs index 9e5a527..3cf7bd7 100644 --- a/src/DotnetEventBus/Repositories/InMemoryRepository.cs +++ b/src/DotnetEventBus/Repositories/InMemoryRepository.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -11,7 +9,7 @@ namespace DotnetEventBus.Repositories; /// In-memory repository implementation using a thread-safe dictionary. /// Suitable for testing and single-process deployments. /// -public sealed class InMemoryRepository : IRepository where T : class +public class InMemoryRepository : IRepository where T : class { private readonly Dictionary _store = new(); private readonly ReaderWriterLockSlim _lock = new(); @@ -56,7 +54,7 @@ public async Task> GetAllAsync(CancellationToken cancellationToke /// public async Task AddAsync(T entity, CancellationToken cancellationToken = default) { - if (entity is null) + if (entity == null) throw new ArgumentNullException(nameof(entity)); var id = GetEntityId(entity); @@ -83,7 +81,7 @@ public async Task AddAsync(T entity, CancellationToken cancellationToken = de /// public async Task UpdateAsync(T entity, CancellationToken cancellationToken = default) { - if (entity is null) + if (entity == null) throw new ArgumentNullException(nameof(entity)); var id = GetEntityId(entity); @@ -129,7 +127,7 @@ public async Task DeleteAsync(string id, CancellationToken cancellationTok /// public async Task DeleteAsync(T entity, CancellationToken cancellationToken = default) { - if (entity is null) + if (entity == null) throw new ArgumentNullException(nameof(entity)); var id = GetEntityId(entity); diff --git a/src/DotnetEventBus/Repositories/SubscriptionRepository.cs b/src/DotnetEventBus/Repositories/SubscriptionRepository.cs index 8b99b67..26e0e51 100644 --- a/src/DotnetEventBus/Repositories/SubscriptionRepository.cs +++ b/src/DotnetEventBus/Repositories/SubscriptionRepository.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -63,7 +61,7 @@ public interface ISubscriptionRepository : IRepository /// /// In-memory implementation of the subscription repository. /// -public sealed class InMemorySubscriptionRepository : InMemoryRepository, ISubscriptionRepository +public class InMemorySubscriptionRepository : InMemoryRepository, ISubscriptionRepository { public async Task> GetByEventTypeAsync(string eventType, CancellationToken cancellationToken = default) { diff --git a/src/DotnetEventBus/Services/BatchEventPublisher.cs b/src/DotnetEventBus/Services/BatchEventPublisher.cs index d1e901c..72b45ab 100644 --- a/src/DotnetEventBus/Services/BatchEventPublisher.cs +++ b/src/DotnetEventBus/Services/BatchEventPublisher.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -19,7 +17,7 @@ namespace DotnetEventBus.Services; /// Collects events and flushes them according to size or time triggers. /// Why: Reduces per-event overhead and improves system throughput significantly. /// -public sealed class BatchEventPublisher +public class BatchEventPublisher { private readonly ILogger _logger; private readonly List _buffer = []; @@ -118,7 +116,7 @@ public async Task FlushAsync() } } - if (batch is not null) + if (batch != null) { await FlushBatchAsync(batch); } @@ -153,7 +151,7 @@ public BatchPublisherStats GetStats() private async Task FlushBatchAsync(EventBatch batch) { - if (_flushHandler is null) + if (_flushHandler == null) { _logger.LogWarning("No flush handler configured for batch publisher"); return; @@ -176,7 +174,7 @@ private async Task FlushBatchAsync(EventBatch batch) /// /// Statistics about batch publisher state. /// -public sealed class BatchPublisherStats +public class BatchPublisherStats { public int BufferedEventCount { get; set; } public int BufferedEventSize { get; set; } diff --git a/src/DotnetEventBus/Services/DeadLetterService.cs b/src/DotnetEventBus/Services/DeadLetterService.cs index 0abe27d..fbd333a 100644 --- a/src/DotnetEventBus/Services/DeadLetterService.cs +++ b/src/DotnetEventBus/Services/DeadLetterService.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -60,7 +58,7 @@ public interface IDeadLetterService /// /// Statistics about the dead letter queue. /// -public sealed class DeadLetterStatistics +public class DeadLetterStatistics { public int TotalEntries { get; set; } public int PendingEntries { get; set; } @@ -75,7 +73,7 @@ public sealed class DeadLetterStatistics /// /// Default implementation of the dead letter service. /// -public sealed class DeadLetterService : IDeadLetterService +public class DeadLetterService : IDeadLetterService { private readonly IDeadLetterRepository _repository; private readonly IEventBus? _eventBus; @@ -118,13 +116,13 @@ public async Task ReprocessEntryAsync(string entryId, CancellationToken ca throw new ArgumentException("Entry ID cannot be empty", nameof(entryId)); var entry = await _repository.GetByIdAsync(entryId, cancellationToken); - if (entry is null) + if (entry == null) { _logger?.LogWarning("Dead letter entry {EntryId} not found", entryId); return false; } - if (_eventBus is null) + if (_eventBus == null) { _logger?.LogError("Event bus not available for reprocessing dead letter entry {EntryId}", entryId); entry.MarkAsReprocessFailed("Event bus not available"); @@ -169,7 +167,7 @@ public async Task MarkAsReviewedAsync(string entryId, string? reason = null, Can throw new ArgumentException("Entry ID cannot be empty", nameof(entryId)); var entry = await _repository.GetByIdAsync(entryId, cancellationToken); - if (entry is null) + if (entry == null) throw new InvalidOperationException($"Dead letter entry '{entryId}' not found"); entry.MarkAsReviewed(reason); diff --git a/src/DotnetEventBus/Services/EventBus.cs b/src/DotnetEventBus/Services/EventBus.cs index ffb5f42..5c89829 100644 --- a/src/DotnetEventBus/Services/EventBus.cs +++ b/src/DotnetEventBus/Services/EventBus.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -19,7 +17,7 @@ namespace DotnetEventBus.Services; /// /// In-process event bus implementation supporting pub/sub and request/reply patterns. /// -public sealed class EventBus : IEventBus +public class EventBus : IEventBus { private readonly EventBusOptions _options; private readonly ILogger? _logger; @@ -66,7 +64,7 @@ public async Task PublishAsync( CancellationToken cancellationToken = default) where TEvent : class { - if (@event is null) + if (@event == null) throw new ArgumentNullException(nameof(@event)); var eventType = typeof(TEvent).FullName ?? typeof(TEvent).Name; @@ -79,9 +77,9 @@ public async Task PublishAsync( string? correlationId = null, CancellationToken cancellationToken = default) { - if (@event is null) + if (@event == null) throw new ArgumentNullException(nameof(@event)); - if (eventType is null) + if (eventType == null) throw new ArgumentNullException(nameof(eventType)); var startTime = DateTime.UtcNow; @@ -153,7 +151,7 @@ public async Task SendAsync( where TRequest : class where TResponse : class { - if (request is null) + if (request == null) throw new ArgumentNullException(nameof(request)); throw new NotImplementedException("Request/reply pattern requires distributed transport configuration"); @@ -162,7 +160,7 @@ public async Task SendAsync( public IDisposable Subscribe(IEventHandler handler) where TEvent : class { - if (handler is null) + if (handler == null) throw new ArgumentNullException(nameof(handler)); var eventType = typeof(TEvent).FullName ?? typeof(TEvent).Name; @@ -193,7 +191,7 @@ public IDisposable Subscribe( int priority = 0) where TEvent : class { - if (handler is null) + if (handler == null) throw new ArgumentNullException(nameof(handler)); var eventType = typeof(TEvent).FullName ?? typeof(TEvent).Name; diff --git a/src/DotnetEventBus/Services/HandlerInvoker.cs b/src/DotnetEventBus/Services/HandlerInvoker.cs index 939ea30..cf5878d 100644 --- a/src/DotnetEventBus/Services/HandlerInvoker.cs +++ b/src/DotnetEventBus/Services/HandlerInvoker.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -41,7 +39,7 @@ public interface IHandlerInvoker /// /// Default implementation of handler invocation using reflection. /// -public sealed class HandlerInvoker : IHandlerInvoker +public class HandlerInvoker : IHandlerInvoker { private readonly ILogger? _logger; private readonly Dictionary<(Type, Type), MethodInfo> _methodCache = new(); @@ -54,9 +52,9 @@ public HandlerInvoker(ILogger? logger = null) public async Task InvokeAsync(IEventHandler handler, object @event, CancellationToken cancellationToken = default) { - if (handler is null) + if (handler == null) throw new ArgumentNullException(nameof(handler)); - if (@event is null) + if (@event == null) throw new ArgumentNullException(nameof(@event)); var eventType = @event.GetType(); @@ -64,7 +62,7 @@ public async Task InvokeAsync(IEventHandler handler, object @event, Cancellation try { var method = GetHandleMethod(handler.GetType(), eventType); - if (method is null) + if (method == null) throw new InvalidOperationException( $"Handler {handler.GetType().Name} does not have a compatible Handle method for {eventType.Name}"); @@ -87,9 +85,9 @@ public async Task InvokeAsync(IEventHandler handler, object @event, Cancellation public async Task InvokeRequestAsync(object handler, object request, CancellationToken cancellationToken = default) { - if (handler is null) + if (handler == null) throw new ArgumentNullException(nameof(handler)); - if (request is null) + if (request == null) throw new ArgumentNullException(nameof(request)); var requestType = request.GetType(); @@ -106,7 +104,7 @@ public async Task InvokeAsync(IEventHandler handler, object @event, Cancellation m.ReturnType.IsGenericType && m.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)); - if (method is null) + if (method == null) throw new InvalidOperationException( $"Handler {handlerType.Name} does not have a compatible Handle method for request {requestType.Name}"); @@ -132,20 +130,20 @@ public async Task InvokeAsync(IEventHandler handler, object @event, Cancellation public bool CanHandle(IEventHandler handler, Type eventType) { - if (handler is null) + if (handler == null) throw new ArgumentNullException(nameof(handler)); - if (eventType is null) + if (eventType == null) throw new ArgumentNullException(nameof(eventType)); if (handler is IPolymorphicHandler polymorphic) return polymorphic.CanHandle(eventType); - return GetHandleMethod(handler.GetType(), eventType) is not null; + return GetHandleMethod(handler.GetType(), eventType) != null; } public IEnumerable GetSupportedEventTypes(IEventHandler handler) { - if (handler is null) + if (handler == null) throw new ArgumentNullException(nameof(handler)); var supportedTypes = new List(); diff --git a/src/DotnetEventBus/Services/IEventBus.cs b/src/DotnetEventBus/Services/IEventBus.cs index ca2b9b8..fa5f760 100644 --- a/src/DotnetEventBus/Services/IEventBus.cs +++ b/src/DotnetEventBus/Services/IEventBus.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Services/PredicateSubscriptionExtensions.cs b/src/DotnetEventBus/Services/PredicateSubscriptionExtensions.cs index 1b00d4e..9dacaa1 100644 --- a/src/DotnetEventBus/Services/PredicateSubscriptionExtensions.cs +++ b/src/DotnetEventBus/Services/PredicateSubscriptionExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Services/SubscriptionManager.cs b/src/DotnetEventBus/Services/SubscriptionManager.cs index 85efaeb..1839d26 100644 --- a/src/DotnetEventBus/Services/SubscriptionManager.cs +++ b/src/DotnetEventBus/Services/SubscriptionManager.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -50,7 +48,7 @@ public interface ISubscriptionManager /// /// Information about a subscription. /// -public sealed class SubscriptionInfo +public class SubscriptionInfo { public string Id { get; set; } = string.Empty; public string EventType { get; set; } = string.Empty; @@ -65,7 +63,7 @@ public sealed class SubscriptionInfo /// /// Statistics about subscriptions. /// -public sealed class SubscriptionStatistics +public class SubscriptionStatistics { public int TotalSubscriptions { get; set; } public int ActiveSubscriptions { get; set; } @@ -80,7 +78,7 @@ public sealed class SubscriptionStatistics /// /// Default implementation of subscription management. /// -public sealed class SubscriptionManager : ISubscriptionManager +public class SubscriptionManager : ISubscriptionManager { private readonly ISubscriptionRepository _repository; private readonly ILogger? _logger; diff --git a/src/DotnetEventBus/Utilities/CollectionExtensions.cs b/src/DotnetEventBus/Utilities/CollectionExtensions.cs index 4e045e2..73cf0b1 100644 --- a/src/DotnetEventBus/Utilities/CollectionExtensions.cs +++ b/src/DotnetEventBus/Utilities/CollectionExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -46,7 +44,7 @@ public static IEnumerable> Batch(this IEnumerable items, in /// Determines if a collection is null or empty. /// public static bool IsNullOrEmpty(this IEnumerable? source) => - source is null || !source.Any(); + source == null || !source.Any(); /// /// Safely returns the first element or a default value if the collection is empty. @@ -168,7 +166,7 @@ public static IEnumerable> AsPages(this IEnumerable source, int pa /// /// Represents a page of items from a paginated collection. /// -public sealed class Page +public class Page { public int PageNumber { get; } public int PageSize { get; } diff --git a/src/DotnetEventBus/Utilities/DateTimeExtensions.cs b/src/DotnetEventBus/Utilities/DateTimeExtensions.cs index fb687d5..81f0d72 100644 --- a/src/DotnetEventBus/Utilities/DateTimeExtensions.cs +++ b/src/DotnetEventBus/Utilities/DateTimeExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Utilities/ReflectionHelper.cs b/src/DotnetEventBus/Utilities/ReflectionHelper.cs index 1495a2e..477d411 100644 --- a/src/DotnetEventBus/Utilities/ReflectionHelper.cs +++ b/src/DotnetEventBus/Utilities/ReflectionHelper.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -52,10 +50,10 @@ public static IEnumerable GetMethodsBySignature( var bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase; var methods = type.GetMethods(bindingFlags).Where(m => m.Name.Equals(methodName, StringComparison.OrdinalIgnoreCase)); - if (returnType is not null) + if (returnType != null) methods = methods.Where(m => m.ReturnType == returnType); - if (parameterTypes is not null) + if (parameterTypes != null) methods = methods.Where(m => { var parameters = m.GetParameters(); @@ -139,7 +137,7 @@ public static void SetPropertyValue(object obj, string propertyName, object? val var parameterTypes = parameters.Select(p => p?.GetType() ?? typeof(object)).ToArray(); var method = obj.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null); - if (method is null) + if (method == null) throw new MethodAccessException($"Method {methodName} not found on type {obj.GetType().Name}"); return method.Invoke(obj, parameters); diff --git a/src/DotnetEventBus/Utilities/StringExtensions.cs b/src/DotnetEventBus/Utilities/StringExtensions.cs index 55e462c..63a58c1 100644 --- a/src/DotnetEventBus/Utilities/StringExtensions.cs +++ b/src/DotnetEventBus/Utilities/StringExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect diff --git a/src/DotnetEventBus/Utilities/TypeExtensions.cs b/src/DotnetEventBus/Utilities/TypeExtensions.cs index 36f3346..e79d1d5 100644 --- a/src/DotnetEventBus/Utilities/TypeExtensions.cs +++ b/src/DotnetEventBus/Utilities/TypeExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -22,7 +20,7 @@ public static class TypeExtensions /// public static string GetFriendlyName(this Type type) { - if (type is null) + if (type == null) throw new ArgumentNullException(nameof(type)); if (!type.IsGenericType) @@ -38,7 +36,7 @@ public static string GetFriendlyName(this Type type) /// public static bool IsAssignableFromNullable(this Type type, Type? other) { - return other is not null && type.IsAssignableFrom(other); + return other != null && type.IsAssignableFrom(other); } /// @@ -46,7 +44,7 @@ public static bool IsAssignableFromNullable(this Type type, Type? other) /// public static bool Implements(this Type type) where TInterface : class { - if (type is null) + if (type == null) throw new ArgumentNullException(nameof(type)); return typeof(TInterface).IsAssignableFrom(type); @@ -57,10 +55,10 @@ public static bool Implements(this Type type) where TInterface : cla /// public static bool IsNullableType(this Type type) { - if (type is null) + if (type == null) return false; - return Nullable.GetUnderlyingType(type) is not null || !type.IsValueType; + return Nullable.GetUnderlyingType(type) != null || !type.IsValueType; } /// @@ -68,7 +66,7 @@ public static bool IsNullableType(this Type type) /// public static IEnumerable GetAllInterfaces(this Type type) { - if (type is null) + if (type == null) throw new ArgumentNullException(nameof(type)); return type.GetInterfaces().Concat(new[] { type }).Where(t => t.IsInterface); @@ -79,7 +77,7 @@ public static IEnumerable GetAllInterfaces(this Type type) /// public static bool IsInstantiable(this Type type) { - if (type is null) + if (type == null) return false; return !type.IsAbstract && !type.IsInterface && type.IsClass; @@ -91,7 +89,7 @@ public static bool IsInstantiable(this Type type) /// public static string GetFullTypeNameWithGenerics(this Type type) { - if (type is null) + if (type == null) throw new ArgumentNullException(nameof(type)); if (!type.IsGenericType) @@ -108,7 +106,7 @@ public static string GetFullTypeNameWithGenerics(this Type type) /// public static bool InheritsFrom(this Type type, Type baseType) { - if (type is null || baseType is null) + if (type == null || baseType == null) return false; return baseType.IsGenericTypeDefinition @@ -121,7 +119,7 @@ public static bool InheritsFrom(this Type type, Type baseType) /// public static IEnumerable GetAllPublicProperties(this Type type) { - if (type is null) + if (type == null) throw new ArgumentNullException(nameof(type)); return type.GetProperties( diff --git a/src/DotnetEventBus/Utilities/ValidationHelper.cs b/src/DotnetEventBus/Utilities/ValidationHelper.cs index d22bec4..dd6c869 100644 --- a/src/DotnetEventBus/Utilities/ValidationHelper.cs +++ b/src/DotnetEventBus/Utilities/ValidationHelper.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Utilities; /// Provides fluent validation API for event bus parameters and configurations. /// Why: Centralized validation ensures consistent error messages and validation rules. /// -public sealed class ValidationHelper +public class ValidationHelper { private readonly List _errors = []; @@ -39,7 +37,7 @@ public ValidationHelper RequireNotEmpty(string? value, string fieldName) /// public ValidationHelper RequireNotNull(T? value, string fieldName) where T : class { - if (value is null) + if (value == null) { _errors.Add($"{fieldName} is required and cannot be null"); } @@ -65,7 +63,7 @@ public ValidationHelper RequirePattern(string? value, string pattern, string fie /// public ValidationHelper RequireLength(string? value, int minLength, int maxLength, string fieldName) { - if (value is not null) + if (value != null) { if (value.Length < minLength || value.Length > maxLength) { @@ -185,7 +183,7 @@ public void ThrowIfInvalid() /// /// Exception thrown when validation fails. /// -public sealed class ValidationException : Exception +public class ValidationException : Exception { public ValidationException(string message) : base(message) { } } diff --git a/src/DotnetEventBus/Workers/DeadLetterProcessor.cs b/src/DotnetEventBus/Workers/DeadLetterProcessor.cs index 1aaf8f0..f06d273 100644 --- a/src/DotnetEventBus/Workers/DeadLetterProcessor.cs +++ b/src/DotnetEventBus/Workers/DeadLetterProcessor.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -20,7 +18,7 @@ namespace DotnetEventBus.Workers; /// Attempts to reprocess failed events and track retry statistics. /// Why: Ensures no events are permanently lost and provides visibility into failures. /// -public sealed class DeadLetterProcessor : BackgroundService +public class DeadLetterProcessor : BackgroundService { private readonly ILogger _logger; private readonly TimeSpan _processingInterval; @@ -158,7 +156,7 @@ public IEnumerable GetAllItems() public bool RemoveItem(string id) { var item = _deadLetterQueue.FirstOrDefault(x => x.Id == id); - if (item is not null) + if (item != null) { _deadLetterQueue.Remove(item); return true; @@ -168,7 +166,7 @@ public bool RemoveItem(string id) } } -public sealed class DeadLetterItem +public class DeadLetterItem { public string? Id { get; set; } public string? EventType { get; set; } @@ -189,7 +187,7 @@ public enum DeadLetterStatus Failed } -public sealed class DeadLetterStats +public class DeadLetterStats { public int TotalItems { get; set; } public int PendingItems { get; set; } diff --git a/tests/DotnetEventBus.Tests/DotnetEventBus.Tests.csproj b/tests/DotnetEventBus.Tests/DotnetEventBus.Tests.csproj index b495525..27d244c 100644 --- a/tests/DotnetEventBus.Tests/DotnetEventBus.Tests.csproj +++ b/tests/DotnetEventBus.Tests/DotnetEventBus.Tests.csproj @@ -15,7 +15,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/DotnetEventBus.Tests/EventBusMockTests.cs b/tests/DotnetEventBus.Tests/EventBusMockTests.cs index 7358dd8..19bbcb5 100644 --- a/tests/DotnetEventBus.Tests/EventBusMockTests.cs +++ b/tests/DotnetEventBus.Tests/EventBusMockTests.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -15,7 +13,7 @@ namespace DotnetEventBus.Tests; -public sealed class EventBusMockTests +public class EventBusMockTests { [Fact] public async Task PublishAsync_WithFailingHandler_ShouldAddEntryToDeadLetterRepository() diff --git a/tests/DotnetEventBus.Tests/EventBusTests.cs b/tests/DotnetEventBus.Tests/EventBusTests.cs index 3375f33..82c4448 100644 --- a/tests/DotnetEventBus.Tests/EventBusTests.cs +++ b/tests/DotnetEventBus.Tests/EventBusTests.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Tests; /// /// Test event class for testing purposes. /// -public sealed class TestEvent +public class TestEvent { public string Data { get; set; } = string.Empty; public int Value { get; set; } @@ -26,7 +24,7 @@ public sealed class TestEvent /// /// Test handler implementation. /// -public sealed class TestEventHandler : EventHandlerBase +public class TestEventHandler : EventHandlerBase { public int CallCount { get; set; } @@ -40,7 +38,7 @@ public override async Task Handle(TestEvent @event, CancellationToken cancellati /// /// Unit tests for the event bus. /// -public sealed class EventBusTests +public class EventBusTests { private readonly ServiceCollection _services; private readonly IEventBus _eventBus; diff --git a/tests/DotnetEventBus.Tests/ModelBehaviorTests.cs b/tests/DotnetEventBus.Tests/ModelBehaviorTests.cs index 1073755..643cc39 100644 --- a/tests/DotnetEventBus.Tests/ModelBehaviorTests.cs +++ b/tests/DotnetEventBus.Tests/ModelBehaviorTests.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -11,7 +9,7 @@ namespace DotnetEventBus.Tests; -public sealed class EventMessageModelTests +public class EventMessageModelTests { [Fact] public void CreateRetry_ShouldIncrementProcessingAttemptsAndPreserveHeaders() @@ -59,7 +57,7 @@ public void GetHeader_WithUnknownKey_ShouldReturnNull() } } -public sealed class SubscriptionModelTests +public class SubscriptionModelTests { [Fact] public void Disable_ThenEnable_ShouldToggleIsActiveCorrectly() diff --git a/tests/DotnetEventBus.Tests/PublishResultTests.cs b/tests/DotnetEventBus.Tests/PublishResultTests.cs index 9ec36c3..678dc4f 100644 --- a/tests/DotnetEventBus.Tests/PublishResultTests.cs +++ b/tests/DotnetEventBus.Tests/PublishResultTests.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -11,7 +9,7 @@ namespace DotnetEventBus.Tests; -public sealed class PublishResultTests +public class PublishResultTests { [Fact] public void AddSuccessfulHandler_ShouldIncrementHandlersInvokedAndAppendToList() diff --git a/tests/DotnetEventBus.Tests/RepositoryTests.cs b/tests/DotnetEventBus.Tests/RepositoryTests.cs index b836171..330b453 100644 --- a/tests/DotnetEventBus.Tests/RepositoryTests.cs +++ b/tests/DotnetEventBus.Tests/RepositoryTests.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -14,7 +12,7 @@ namespace DotnetEventBus.Tests; /// /// Unit tests for repository implementations. /// -public sealed class InMemoryRepositoryTests +public class InMemoryRepositoryTests { [Fact] public async Task AddAsync_WithValidEntity_ShouldAddAndRetrieve() @@ -141,7 +139,7 @@ public async Task ClearAsync_ShouldRemoveAllEntities() /// /// Unit tests for event message repository. /// -public sealed class EventMessageRepositoryTests +public class EventMessageRepositoryTests { private readonly IEventMessageRepository _repository = new InMemoryEventMessageRepository(); @@ -207,7 +205,7 @@ public async Task DeleteOldMessagesAsync_ShouldRemoveOldMessages() /// /// Unit tests for dead letter repository. /// -public sealed class DeadLetterRepositoryTests +public class DeadLetterRepositoryTests { private readonly IDeadLetterRepository _repository = new InMemoryDeadLetterRepository(); @@ -270,7 +268,7 @@ public async Task CountByStatusAsync_ShouldReturnCorrectCount() /// /// Test entity for repository testing. /// -public sealed class TestEntity +public class TestEntity { public string Id { get; set; } = Guid.NewGuid().ToString(); public string Name { get; set; } = string.Empty; diff --git a/tests/DotnetEventBus.Tests/ServiceTests.cs b/tests/DotnetEventBus.Tests/ServiceTests.cs index 6e8e503..a3e2bec 100644 --- a/tests/DotnetEventBus.Tests/ServiceTests.cs +++ b/tests/DotnetEventBus.Tests/ServiceTests.cs @@ -1,5 +1,3 @@ -#nullable enable - // ============================================================================= // Author: Vladyslav Zaiets | https://sarmkadan.com // CTO & Software Architect @@ -17,7 +15,7 @@ namespace DotnetEventBus.Tests; /// /// Unit tests for DeadLetterService. /// -public sealed class DeadLetterServiceTests +public class DeadLetterServiceTests { private readonly IDeadLetterRepository _repository = new InMemoryDeadLetterRepository(); private readonly IDeadLetterService _service; @@ -108,7 +106,7 @@ public async Task ArchiveOldEntriesAsync_ShouldArchiveOldEntries() /// /// Unit tests for SubscriptionManager. /// -public sealed class SubscriptionManagerTests +public class SubscriptionManagerTests { private readonly ISubscriptionRepository _repository = new InMemorySubscriptionRepository(); private readonly ISubscriptionManager _manager; @@ -177,84 +175,10 @@ public async Task GetStatisticsAsync_ShouldReturnAccurateStats() } } -/// -/// Unit tests for dead letter queue exception handling. -/// -public sealed class DeadLetterExceptionHandlingTests -{ - private readonly IDeadLetterRepository _repository = new InMemoryDeadLetterRepository(); - private readonly IDeadLetterService _service; - - public DeadLetterExceptionHandlingTests() - { - var services = new ServiceCollection(); - services.AddEventBus(); - var provider = services.BuildServiceProvider(); - var eventBus = provider.GetRequiredService(); - _service = new DeadLetterService(_repository, eventBus); - } - - [Fact] - public async Task DeadLetterEntry_ShouldCaptureFullExceptionDetails() - { - // Arrange - Create an exception with a specific stack trace - var originalException = new InvalidOperationException("Test operation failed"); - - var msg = new EventMessage("TestEvent", "test payload"); - - // Act - Create a dead letter entry with the exception - var entry = new DeadLetterEntry(msg, "TestHandler", originalException, 3); - await _repository.AddAsync(entry); - - // Assert - Verify that the exception details are captured - Assert.NotNull(entry.ExceptionMessage); - Assert.NotNull(entry.ExceptionStackTrace); - Assert.Contains("InvalidOperationException", entry.ExceptionStackTrace); - Assert.Contains("Test operation failed", entry.ExceptionStackTrace); - Assert.Contains("TestHandler", entry.FailedHandlerName); - } - - [Fact] - public async Task DeadLetterEntry_WithInnerException_ShouldCaptureFullStackTrace() - { - // Arrange - Create an exception with an inner exception - var innerException = new ArgumentNullException("param1", "Inner error"); - var outerException = new InvalidOperationException("Outer error", innerException); - - var msg = new EventMessage("TestEvent", "test payload"); - - // Act - Create a dead letter entry with the exception chain - var entry = new DeadLetterEntry(msg, "TestHandler", outerException, 3); - await _repository.AddAsync(entry); - - // Assert - Verify that both exceptions are captured in the stack trace - Assert.NotNull(entry.ExceptionStackTrace); - Assert.Contains("InvalidOperationException", entry.ExceptionStackTrace); - Assert.Contains("ArgumentNullException", entry.ExceptionStackTrace); - Assert.Contains("Outer error", entry.ExceptionStackTrace); - Assert.Contains("Inner error", entry.ExceptionStackTrace); - } - - [Fact] - public async Task DeadLetterEntry_WithNullException_ShouldHandleGracefully() - { - // Arrange - var msg = new EventMessage("TestEvent", "test payload"); - - // Act - Create a dead letter entry with null exception - var entry = new DeadLetterEntry(msg, "TestHandler", null, 3); - await _repository.AddAsync(entry); - - // Assert - Verify graceful handling - Assert.Equal("Unknown exception", entry.ExceptionMessage); - Assert.Null(entry.ExceptionStackTrace); - } -} - /// /// Unit tests for HandlerInvoker. /// -public sealed class HandlerInvokerTests +public class HandlerInvokerTests { [Fact] public async Task InvokeAsync_WithValidHandler_ShouldInvoke() @@ -318,7 +242,7 @@ public void GetSupportedEventTypes_ShouldReturnHandlerEventTypes() /// /// Unit tests for configuration and options. /// -public sealed class ConfigurationTests +public class ConfigurationTests { [Fact] public void EventBusOptions_Validate_ShouldThrowOnInvalidOptions()