using System;
using Svrnty.CQRS.Events.Abstractions.Delivery;
using Svrnty.CQRS.Events.Delivery;
using Svrnty.CQRS.Events.Abstractions.EventStore;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Svrnty.CQRS.Events.Abstractions;
using Svrnty.CQRS.Events.Abstractions.Subscriptions;
namespace Svrnty.CQRS.Events.Subscriptions;
///
/// Service collection extensions for persistent subscriptions.
///
public static class ServiceCollectionExtensions
{
///
/// Add persistent subscription support to the service collection.
///
/// The service collection.
/// If true, uses in-memory store. Otherwise, expects a persistent store to be registered separately.
/// If true, enables background service for automatic event delivery to subscriptions.
/// The service collection for chaining.
public static IServiceCollection AddPersistentSubscriptions(
this IServiceCollection services,
bool useInMemoryStore = true,
bool enableBackgroundDelivery = true)
{
// Register subscription manager
services.AddSingleton();
// Register Phase 8 event delivery service
services.AddSingleton();
// Register in-memory store if requested
if (useInMemoryStore)
{
services.AddSingleton();
}
// Decorate the main IEventDeliveryService with Phase 8 integration
// This wraps the existing event delivery to also notify persistent subscriptions
DecorateEventDeliveryService(services);
// Register background delivery service if requested
// NOTE: SubscriptionDeliveryHostedService is temporarily disabled pending redesign
// to work with ICorrelatedEvent which doesn't have Sequence/EventType properties
// if (enableBackgroundDelivery)
// {
// services.AddHostedService();
// }
return services;
}
private static void DecorateEventDeliveryService(IServiceCollection services)
{
// Find the existing IEventDeliveryService registration
var existingDescriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IEventDeliveryService));
if (existingDescriptor == null)
{
// If not registered yet, this will be called before AddSvrntyEvents
// The decorator will be registered anyway and will work when the service is added
return;
}
// Remove the existing registration
services.Remove(existingDescriptor);
// Re-register the original implementation with a different service type
services.Add(ServiceDescriptor.Describe(
typeof(Svrnty.CQRS.Events.Delivery.EventDeliveryService),
existingDescriptor.ImplementationType!,
existingDescriptor.Lifetime));
// Register the decorator as IEventDeliveryService
services.Add(ServiceDescriptor.Describe(
typeof(IEventDeliveryService),
sp =>
{
var inner = sp.GetRequiredService();
var persistentDeliveryService = sp.GetService();
var subscriptionStore = sp.GetService();
var logger = sp.GetRequiredService>();
return new PersistentSubscriptionDeliveryDecorator(inner, persistentDeliveryService, subscriptionStore, logger);
},
existingDescriptor.Lifetime));
}
}