diff --git a/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClient.cs b/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClient.cs index 9bd8dc9..f7f4d68 100644 --- a/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClient.cs +++ b/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClient.cs @@ -11,6 +11,9 @@ namespace LeanCode.Pipe.TestClient; +/// +/// LeanPipe client designed to be used in the integration tests. +/// public class LeanPipeTestClient : IAsyncDisposable { private readonly ConcurrentDictionary subscriptions = @@ -23,6 +26,11 @@ public class LeanPipeTestClient : IAsyncDisposable public IReadOnlyDictionary Subscriptions => subscriptions; + /// URL on which LeanPipe is exposed at. + /// Type catalog containing all topics and notifications. + /// Underneath hub connection config. + /// Serializer options used for deserializing notifications. + /// Time to wait for subscribe/unsubscribe response before considering failure. public LeanPipeTestClient( Uri leanPipeUrl, TypesCatalog leanPipeTypes, @@ -57,6 +65,7 @@ public LeanPipeTestClient( ); } + /// Unsubscription result, if it doesn't time out. public async Task UnsubscribeAsync( TTopic topic, CancellationToken ct = default @@ -82,6 +91,8 @@ public LeanPipeTestClient( return result; } + /// Connects if there is no active connection. + /// Subscription result, if it doesn't time out. public async Task SubscribeAsync( TTopic topic, CancellationToken ct = default @@ -119,9 +130,7 @@ public LeanPipeTestClient( public Task ConnectAsync(CancellationToken ct = default) => hubConnection.StartAsync(ct); - /// - /// Also clears all subscriptions. - /// + /// Also clears all subscriptions. public Task DisconnectAsync(CancellationToken ct = default) { foreach (var subscription in subscriptions.Values) diff --git a/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClientExtensions.cs b/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClientExtensions.cs index 33d954d..a2a7e5f 100644 --- a/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClientExtensions.cs +++ b/publisher/src/LeanCode.Pipe.TestClient/LeanPipeTestClientExtensions.cs @@ -6,6 +6,12 @@ public static class LeanPipeTestClientExtensions { private static readonly TimeSpan DefaultNotificationAwaitTimeout = TimeSpan.FromSeconds(10); + /// + /// Subscribe to a topic instance or throw if it fails for any reason. + /// + /// Topic instance to subscribe to. + /// Subscription ID. + /// The subscription failed for any reason. public static async Task SubscribeSuccessAsync( this LeanPipeTestClient client, TTopic topic, @@ -30,6 +36,12 @@ public static async Task SubscribeSuccessAsync( } } + /// + /// Unsubscribe from a topic instance or throw if it fails for any reason. + /// + /// Topic instance to unsubscribe from. + /// Subscription ID. + /// The unsubscription failed for any reason. public static async Task UnsubscribeSuccessAsync( this LeanPipeTestClient client, TTopic topic, @@ -54,6 +66,17 @@ public static async Task UnsubscribeSuccessAsync( } } + /// + /// Returns a task, which completes when the next notification on the topic is received. + /// + /// + /// The task should be collected before the action which triggers notification publish + /// and awaited after the trigger. + /// Otherwise there is a possibility that the notification after the expected one is awaited. + /// Topic instance on which notification is to be awaited. + /// Timeout after which the notification is assumed to be not delivered. + /// Task containing received notification. + /// The topic instance received no notifications during the timeout. public static async Task WaitForNextNotificationOn( this LeanPipeTestClient client, TTopic topic, diff --git a/publisher/src/LeanCode.Pipe/BasicTopicKeys.cs b/publisher/src/LeanCode.Pipe/BasicTopicKeys.cs index 4c84ce4..a0cf6f4 100644 --- a/publisher/src/LeanCode.Pipe/BasicTopicKeys.cs +++ b/publisher/src/LeanCode.Pipe/BasicTopicKeys.cs @@ -2,9 +2,17 @@ namespace LeanCode.Pipe; +/// +/// Convenience class for implementing topic keys for simple topics. +/// +/// Topic public abstract class BasicTopicKeys : ISubscribingKeys where TT : ITopic { + /// + /// Used to generate SignalR groups keys when client subscribes, unsubscribes + /// or when the message is published. + /// public abstract IEnumerable Get(TT topic); public ValueTask> GetForSubscribingAsync( @@ -13,10 +21,12 @@ LeanPipeContext context ) => ValueTask.FromResult(Get(topic)); } +/// public abstract class BasicTopicKeys : IPublishingKeys where TT : ITopic, IProduceNotification where TN1 : notnull { + /// public abstract IEnumerable Get(TT topic); public ValueTask> GetForSubscribingAsync( @@ -31,6 +41,7 @@ CancellationToken ct ) => ValueTask.FromResult(Get(topic)); } +/// public abstract class BasicTopicKeys : BasicTopicKeys, IPublishingKeys @@ -45,6 +56,7 @@ public ValueTask> GetForPublishingAsync( ) => ValueTask.FromResult(Get(topic)); } +/// public abstract class BasicTopicKeys : BasicTopicKeys, IPublishingKeys @@ -63,6 +75,7 @@ public ValueTask> GetForPublishingAsync( ) => ValueTask.FromResult(Get(topic)); } +/// public abstract class BasicTopicKeys : BasicTopicKeys, IPublishingKeys @@ -83,6 +96,7 @@ public ValueTask> GetForPublishingAsync( ) => ValueTask.FromResult(Get(topic)); } +/// public abstract class BasicTopicKeys : BasicTopicKeys, IPublishingKeys @@ -105,6 +119,7 @@ public ValueTask> GetForPublishingAsync( ) => ValueTask.FromResult(Get(topic)); } +/// public abstract class BasicTopicKeys : BasicTopicKeys, IPublishingKeys @@ -129,6 +144,7 @@ public ValueTask> GetForPublishingAsync( ) => ValueTask.FromResult(Get(topic)); } +/// public abstract class BasicTopicKeys : BasicTopicKeys, IPublishingKeys diff --git a/publisher/src/LeanCode.Pipe/ITopicKeys.cs b/publisher/src/LeanCode.Pipe/ITopicKeys.cs index f58821a..b1a9937 100644 --- a/publisher/src/LeanCode.Pipe/ITopicKeys.cs +++ b/publisher/src/LeanCode.Pipe/ITopicKeys.cs @@ -2,9 +2,16 @@ namespace LeanCode.Pipe; +/// +/// Should be implemented in a single class per topic with +/// for all topics notifications. +/// public interface ISubscribingKeys where TTopic : ITopic { + /// + /// Used to generate SignalR groups keys when client subscribes or unsubscribes. + /// ValueTask> GetForSubscribingAsync(TTopic topic, LeanPipeContext context); } @@ -12,6 +19,9 @@ public interface IPublishingKeys : ISubscribingKeys where TNotification : notnull { + /// + /// Used to generate SignalR groups keys to which send message to. + /// ValueTask> GetForPublishingAsync( TTopic topic, TNotification notification, diff --git a/publisher/src/LeanCode.Pipe/LeanPipeContext.cs b/publisher/src/LeanCode.Pipe/LeanPipeContext.cs index ed754d1..f5728c9 100644 --- a/publisher/src/LeanCode.Pipe/LeanPipeContext.cs +++ b/publisher/src/LeanCode.Pipe/LeanPipeContext.cs @@ -2,6 +2,9 @@ namespace LeanCode.Pipe; +/// +/// Context that is included in all LeanPipe subscriptions. +/// public class LeanPipeContext { public LeanPipeContext(HttpContext httpContext) diff --git a/publisher/src/LeanCode.Pipe/LeanPipeEndpointRouteBuilderExtensions.cs b/publisher/src/LeanCode.Pipe/LeanPipeEndpointRouteBuilderExtensions.cs index f2b8b47..21b4a9b 100644 --- a/publisher/src/LeanCode.Pipe/LeanPipeEndpointRouteBuilderExtensions.cs +++ b/publisher/src/LeanCode.Pipe/LeanPipeEndpointRouteBuilderExtensions.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Routing; @@ -6,17 +7,23 @@ namespace LeanCode.Pipe; public static class LeanPipeEndpointRouteBuilderExtensions { + /// + /// Maps LeanPipe SignalR hub on the specified endpoint. + /// public static IHubEndpointConventionBuilder MapLeanPipe( this IEndpointRouteBuilder endpoints, - string pattern + [StringSyntax("Route")] string pattern ) { return endpoints.MapHub(pattern); } + /// + /// Maps LeanPipe SignalR hub on the specified endpoint. + /// public static IHubEndpointConventionBuilder MapLeanPipe( this IEndpointRouteBuilder endpoints, - string pattern, + [StringSyntax("Route")] string pattern, Action? configureOptions ) { diff --git a/publisher/src/LeanCode.Pipe/LeanPipePublisher.cs b/publisher/src/LeanCode.Pipe/LeanPipePublisher.cs index f36cc89..93f9115 100644 --- a/publisher/src/LeanCode.Pipe/LeanPipePublisher.cs +++ b/publisher/src/LeanCode.Pipe/LeanPipePublisher.cs @@ -4,6 +4,10 @@ namespace LeanCode.Pipe; +/// +/// Allows publishing notifications to instances of . +/// Conveniently used with extension methods from . +/// public class LeanPipePublisher where TTopic : ITopic { @@ -31,6 +35,10 @@ internal async Task PublishAsync( public static class LeanPipePublisherExtensions { + /// + /// Publishes to topic instance using provided SignalR groups keys. + /// Omits publishing keys implemented in . + /// public static async Task PublishAsync( this LeanPipePublisher publisher, IEnumerable keys, @@ -46,6 +54,10 @@ public static async Task PublishAsync( await publisher.PublishAsync(keys, payload, ct); } + /// + /// Publishes to topic instance using SignalR groups keys generated via implementation of + /// . + /// public static async Task PublishAsync( this LeanPipePublisher publisher, TTopic topic, diff --git a/publisher/src/LeanCode.Pipe/LeanPipeServiceCollectionExtensions.cs b/publisher/src/LeanCode.Pipe/LeanPipeServiceCollectionExtensions.cs index 241bbed..b8231b5 100644 --- a/publisher/src/LeanCode.Pipe/LeanPipeServiceCollectionExtensions.cs +++ b/publisher/src/LeanCode.Pipe/LeanPipeServiceCollectionExtensions.cs @@ -8,6 +8,11 @@ namespace LeanCode.Pipe; public static class LeanPipeServiceCollectionExtensions { + /// + /// Adds all classes required for LeanPipe to function to DI. + /// + /// Service builder allowing for overriding default LeanPipe implementations + /// and further configuration. public static LeanPipeServicesBuilder AddLeanPipe( this IServiceCollection services, TypesCatalog topics, @@ -28,6 +33,10 @@ TypesCatalog handlers } } +/// +/// Allows for overriding default LeanPipe implementations +/// and further configuration. +/// public class LeanPipeServicesBuilder { public IServiceCollection Services { get; } @@ -43,6 +52,9 @@ public LeanPipeServicesBuilder(IServiceCollection services, TypesCatalog topics) Services.AddSingleton(new DefaultEnvelopeDeserializer(topics, null)); } + /// + /// Overrides serializing options used in subscription envelope deserializer. + /// public LeanPipeServicesBuilder WithEnvelopeDeserializerOptions(JsonSerializerOptions options) { this.options = options; @@ -50,12 +62,18 @@ public LeanPipeServicesBuilder WithEnvelopeDeserializerOptions(JsonSerializerOpt return this; } + /// + /// Overrides subscription envelope deserializer. + /// public LeanPipeServicesBuilder WithEnvelopeDeserializer(IEnvelopeDeserializer deserializer) { Services.Replace(new ServiceDescriptor(typeof(IEnvelopeDeserializer), deserializer)); return this; } + /// + /// Adds topics from another . + /// public LeanPipeServicesBuilder AddTopics(TypesCatalog newTopics) { topics = topics.Merge(newTopics); @@ -63,6 +81,9 @@ public LeanPipeServicesBuilder AddTopics(TypesCatalog newTopics) return this; } + /// + /// Adds subscription handlers and keys generators from another . + /// public LeanPipeServicesBuilder AddHandlers(TypesCatalog newHandlers) { Services.RegisterGenericTypes( diff --git a/publisher/src/LeanCode.Pipe/SubscriptionHandler.cs b/publisher/src/LeanCode.Pipe/SubscriptionHandler.cs index ac02e3c..d3e0e25 100644 --- a/publisher/src/LeanCode.Pipe/SubscriptionHandler.cs +++ b/publisher/src/LeanCode.Pipe/SubscriptionHandler.cs @@ -12,7 +12,7 @@ ValueTask OnSubscribedAsync( LeanPipeContext context ); - /// Whether subscription was correctly established. + /// Whether subscription was correctly severed. ValueTask OnUnsubscribedAsync( TTopic topic, LeanPipeSubscriber leanPipeSubscriber, diff --git a/publisher/src/LeanCode.Pipe/SubscriptionHandlerWrapper.cs b/publisher/src/LeanCode.Pipe/SubscriptionHandlerWrapper.cs index 03245c0..4b0a35a 100644 --- a/publisher/src/LeanCode.Pipe/SubscriptionHandlerWrapper.cs +++ b/publisher/src/LeanCode.Pipe/SubscriptionHandlerWrapper.cs @@ -9,6 +9,7 @@ ValueTask OnSubscribedAsync( LeanPipeSubscriber leanPipeSubscriber, LeanPipeContext context ); + ValueTask OnUnsubscribedAsync( object topic, LeanPipeSubscriber leanPipeSubscriber,