diff --git a/samples/Sample.Api/Handlers/TheStreamHandler.cs b/samples/Sample.Api/Handlers/TheStreamHandler.cs index 9fdfe2a..ca66a9b 100644 --- a/samples/Sample.Api/Handlers/TheStreamHandler.cs +++ b/samples/Sample.Api/Handlers/TheStreamHandler.cs @@ -9,7 +9,11 @@ public record TestStreamRequest(int SecondsBetween) : IStreamRequest; [MediatorHttpPost("GetStream", "/stream")] public class TheStreamHandler(ILogger logger) : IStreamRequestHandler { - public async IAsyncEnumerable Handle(TestStreamRequest request, [EnumeratorCancellation] CancellationToken cancellationToken) + public async IAsyncEnumerable Handle( + TestStreamRequest request, + RequestContext context, + [EnumeratorCancellation] CancellationToken cancellationToken + ) { while (!cancellationToken.IsCancellationRequested) { diff --git a/samples/Sample/Handlers/AutoRefreshStreamRequestHandler.cs b/samples/Sample/Handlers/AutoRefreshStreamRequestHandler.cs index c9fbf0b..b27f113 100644 --- a/samples/Sample/Handlers/AutoRefreshStreamRequestHandler.cs +++ b/samples/Sample/Handlers/AutoRefreshStreamRequestHandler.cs @@ -7,7 +7,11 @@ namespace Sample.Handlers; public class AutoRefreshStreamRequestHandler : IStreamRequestHandler { [TimerRefresh(3000)] - public async IAsyncEnumerable Handle(AutoRefreshRequest request, [EnumeratorCancellation] CancellationToken cancellationToken) + public async IAsyncEnumerable Handle( + AutoRefreshRequest request, + RequestContext context, + [EnumeratorCancellation] CancellationToken cancellationToken + ) { yield return DateTimeOffset.Now.ToString("h:mm:ss tt"); } diff --git a/samples/Sample/Handlers/MyRequestMiddleware.cs b/samples/Sample/Handlers/MyRequestMiddleware.cs index a390359..7260dc4 100644 --- a/samples/Sample/Handlers/MyRequestMiddleware.cs +++ b/samples/Sample/Handlers/MyRequestMiddleware.cs @@ -4,7 +4,6 @@ namespace Sample.Handlers; -[SingletonMiddleware] public class MyRequestMiddleware(AppSqliteConnection conn) : IRequestMiddleware { public async Task Process( diff --git a/samples/Sample/Handlers/TickerStreamRequestHandler.cs b/samples/Sample/Handlers/TickerStreamRequestHandler.cs index 09d6e89..299d39a 100644 --- a/samples/Sample/Handlers/TickerStreamRequestHandler.cs +++ b/samples/Sample/Handlers/TickerStreamRequestHandler.cs @@ -7,7 +7,11 @@ namespace Sample.Handlers; [SingletonHandler] public class TickerStreamRequestHandler : IStreamRequestHandler { - public async IAsyncEnumerable Handle(TickerRequest request, [EnumeratorCancellation] CancellationToken cancellationToken) + public async IAsyncEnumerable Handle( + TickerRequest request, + RequestContext context, + [EnumeratorCancellation] CancellationToken cancellationToken + ) { for (var i = 0; i < request.Repeat; i++) { diff --git a/samples/Sample/MauiProgram.cs b/samples/Sample/MauiProgram.cs index c6628d5..84e5b9e 100644 --- a/samples/Sample/MauiProgram.cs +++ b/samples/Sample/MauiProgram.cs @@ -2,6 +2,7 @@ using System.Runtime.CompilerServices; using Microsoft.Extensions.Configuration; using Polly; +using Sample.Handlers; namespace Sample; @@ -39,21 +40,17 @@ public static MauiApp CreateMauiApp() builder.Logging.AddDebug(); builder.Services.AddBlazorWebViewDeveloperTools(); #endif - builder.Configuration.AddJsonStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("Sample.appsettings.json")!); + builder.Configuration.AddJsonStream( + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream("Sample.appsettings.json")! + ); builder.Services.AddShinyMediator(x => x .UseMaui() .UseBlazor() - - .AddOfflineAvailabilityMiddleware() .AddPersistentCache() - .AddUserErrorNotificationsMiddleware() - .AddPerformanceLoggingMiddleware() - .AddTimerRefreshStreamMiddleware() - .AddEventExceptionHandlingMiddleware() .AddDataAnnotations() - - .AddHttpClient() .AddMauiHttpDecorator() .AddPrismSupport() @@ -64,6 +61,7 @@ public static MauiApp CreateMauiApp() y.ExpirationScanFrequency = TimeSpan.FromSeconds(5); }) ); + builder.Services.AddSingletonAsImplementedInterfaces(); builder.Services.AddDiscoveredMediatorHandlersFromSample(); builder.Services.AddSingleton(); diff --git a/src/Shiny.Mediator.AppSupport/Middleware/ReplayStreamMiddleware.cs b/src/Shiny.Mediator.AppSupport/Middleware/ReplayStreamMiddleware.cs index 0e79e45..b5f2cea 100644 --- a/src/Shiny.Mediator.AppSupport/Middleware/ReplayStreamMiddleware.cs +++ b/src/Shiny.Mediator.AppSupport/Middleware/ReplayStreamMiddleware.cs @@ -31,7 +31,8 @@ CancellationToken cancellationToken logger.LogDebug("ReplayStream Enabled - {Request}", context.Request); return this.Iterate( - context.Request, + context.Request, + context, next, cancellationToken ); @@ -55,9 +56,9 @@ protected bool IsEnabled(TRequest request, IRequestHandler requestHandler) } - // TODO: add cache protected virtual async IAsyncEnumerable Iterate( TRequest request, + RequestContext context, StreamRequestHandlerDelegate next, [EnumeratorCancellation] CancellationToken ct ) @@ -68,13 +69,21 @@ [EnumeratorCancellation] CancellationToken ct { var item = await cache.Get(requestKey).ConfigureAwait(false); if (item != null) + { + // TODO: need cache date + logger.LogDebug("ReplayStream Cache Hit - {Request}", context.Request); + context.Cache(new CacheContext(requestKey, true, DateTimeOffset.UtcNow)); yield return item.Value; + } } else if (offline != null) { var store = await offline.Get(request); - if (store != null) // TODO: I need context here to ship out date + if (store != null) + { + context.Offline(new OfflineAvailableContext(requestKey, store.Timestamp)); yield return store.Value; + } } if (!internet.IsAvailable) diff --git a/src/Shiny.Mediator/Caching/Infrastructure/CachingRequestMiddleware.cs b/src/Shiny.Mediator/Caching/Infrastructure/CachingRequestMiddleware.cs index 5ba1272..80df5e7 100644 --- a/src/Shiny.Mediator/Caching/Infrastructure/CachingRequestMiddleware.cs +++ b/src/Shiny.Mediator/Caching/Infrastructure/CachingRequestMiddleware.cs @@ -46,7 +46,7 @@ CancellationToken cancellationToken logger.LogDebug("Cache Forced Refresh - {Request}", context.Request); result = await next().ConfigureAwait(false); if (result != null) - cacheService.Set(cacheKey, result, config); + await cacheService.Set(cacheKey, result, config).ConfigureAwait(false); } else { diff --git a/src/Shiny.Mediator/IStreamRequestHandler.cs b/src/Shiny.Mediator/IStreamRequestHandler.cs index 7d0bf0b..5facf0f 100644 --- a/src/Shiny.Mediator/IStreamRequestHandler.cs +++ b/src/Shiny.Mediator/IStreamRequestHandler.cs @@ -3,5 +3,9 @@ namespace Shiny.Mediator; public interface IStreamRequestHandler : IRequestHandler where TRequest : IStreamRequest { - IAsyncEnumerable Handle(TRequest request, CancellationToken cancellationToken); + IAsyncEnumerable Handle( + TRequest request, + RequestContext context, + CancellationToken cancellationToken + ); } \ No newline at end of file diff --git a/src/Shiny.Mediator/Infrastructure/Impl/Mediator_Streams.cs b/src/Shiny.Mediator/Infrastructure/Impl/Mediator_Streams.cs index 540074b..e98227e 100644 --- a/src/Shiny.Mediator/Infrastructure/Impl/Mediator_Streams.cs +++ b/src/Shiny.Mediator/Infrastructure/Impl/Mediator_Streams.cs @@ -51,7 +51,7 @@ public RequestResult> Handle() "Executing streaming request handler {RequestHandlerType}", requestHandler.GetType().FullName ); - return requestHandler.Handle(request, cancellationToken); + return requestHandler.Handle(request, context, cancellationToken); }); var middlewares = scope.GetServices>();