diff --git a/lib/src/client/spinify.dart b/lib/src/client/spinify.dart index 4600143..ef8cb41 100644 --- a/lib/src/client/spinify.dart +++ b/lib/src/client/spinify.dart @@ -113,6 +113,15 @@ abstract base class SpinifyBase implements ISpinify { late final ServerSubscriptionManager _serverSubscriptionManager = ServerSubscriptionManager(_transport); + @override + ({ + Map client, + Map server, + }) get subscriptions => ( + client: _clientSubscriptionManager.subscriptions, + server: _serverSubscriptionManager.subscriptions + ); + /// Init spinify client, override this method to add custom logic. /// This method is called in constructor. /// {@nodoc} @@ -527,10 +536,6 @@ base mixin SpinifyClientSubscriptionMixin on SpinifyBase, SpinifyErrorsMixin { return _clientSubscriptionManager.newSubscription(channel, config); } - @override - Map get subscriptions => - _clientSubscriptionManager.subscriptions; - @override SpinifyClientSubscription? getSubscription(String channel) => _clientSubscriptionManager[channel]; @@ -742,6 +747,10 @@ base mixin SpinifyMetricsMixin on SpinifyBase { timestamp: timestamp, lastUrl: wsMetrics.lastUrl, reconnects: (successful: _connectsSuccessful, total: _connectsTotal), + subscriptions: ( + client: _clientSubscriptionManager.count, + server: _serverSubscriptionManager.count, + ), state: state, receivedCount: wsMetrics.receivedCount, receivedSize: wsMetrics.receivedSize, diff --git a/lib/src/client/spinify_interface.dart b/lib/src/client/spinify_interface.dart index 8a6d70a..cec9c6e 100644 --- a/lib/src/client/spinify_interface.dart +++ b/lib/src/client/spinify_interface.dart @@ -20,7 +20,7 @@ abstract interface class ISpinify ISpinifyAsyncMessageSender, ISpinifyPublicationSender, ISpinifyEventReceiver, - ISpinifyClientSubscriptionsManager, + ISpinifySubscriptionsManager, ISpinifyPresenceOwner, ISpinifyHistoryOwner, ISpinifyRemoteProcedureCall, @@ -75,7 +75,7 @@ abstract interface class ISpinifyEventReceiver { } /// Spinify client subscriptions manager interface. -abstract interface class ISpinifyClientSubscriptionsManager { +abstract interface class ISpinifySubscriptionsManager { /// Create new client-side subscription. /// `newSubscription(channel, config)` allocates a new Subscription /// in the registry or throws an exception if the Subscription @@ -93,15 +93,23 @@ abstract interface class ISpinifyClientSubscriptionsManager { /// in the channel. SpinifyClientSubscription? getSubscription(String channel); - /// Remove the [Subscription] from internal registry + /// Remove the [SpinifySubscription] from internal registry /// and unsubscribe from [SpinifyClientSubscription.channel]. Future removeSubscription(SpinifyClientSubscription subscription); - /// Get map wirth all registered client-side subscriptions. + /// Get map wirth all registered client-side & server-side subscriptions. /// Returns all registered subscriptions, - /// so you can iterate over all and do some action if required - /// (for example, you want to unsubscribe/remove all subscriptions). - Map get subscriptions; + /// so you can iterate over all and do some action if required. + /// + /// For example: + /// ```dart + /// final subscription = spinify.subscriptions.client['chat']!; + /// await subscription.unsubscribe(); + /// ``` + ({ + Map client, + Map server, + }) get subscriptions; } /// Spinify presence owner interface. diff --git a/lib/src/model/metrics.dart b/lib/src/model/metrics.dart index 9195f6f..1e6faff 100644 --- a/lib/src/model/metrics.dart +++ b/lib/src/model/metrics.dart @@ -1,6 +1,18 @@ import 'package:meta/meta.dart'; import 'package:spinify/src/client/state.dart'; +/// Subscription count +/// - total +/// - unsubscribed +/// - subscribing +/// - subscribed +typedef SpinifySubscriptionCount = ({ + int total, + int unsubscribed, + int subscribing, + int subscribed +}); + /// {@template metrics} /// Metrics of Spinify client. /// {@endtemplate} @@ -15,6 +27,7 @@ final class SpinifyMetrics implements Comparable { required this.transferredSize, required this.receivedSize, required this.reconnects, + required this.subscriptions, required this.transferredCount, required this.receivedCount, required this.lastUrl, @@ -35,6 +48,12 @@ final class SpinifyMetrics implements Comparable { /// The total number of times the connection has been re-established. final ({int successful, int total}) reconnects; + /// The number of subscriptions. + final ({ + SpinifySubscriptionCount client, + SpinifySubscriptionCount server + }) subscriptions; + /// The total number of messages sent. final BigInt transferredCount; @@ -55,6 +74,20 @@ final class SpinifyMetrics implements Comparable { 'successful': reconnects.successful, 'total': reconnects.total, }, + 'subscriptions': >{ + 'client': { + 'total': subscriptions.client.total, + 'unsubscribed': subscriptions.client.unsubscribed, + 'subscribing': subscriptions.client.subscribing, + 'subscribed': subscriptions.client.subscribed, + }, + 'server': { + 'total': subscriptions.server.total, + 'unsubscribed': subscriptions.server.unsubscribed, + 'subscribing': subscriptions.server.subscribing, + 'subscribed': subscriptions.server.subscribed, + }, + }, 'transferredSize': transferredSize, 'receivedSize': receivedSize, 'transferredCount': transferredCount, diff --git a/lib/src/subscription/client_subscription_impl.dart b/lib/src/subscription/client_subscription_impl.dart index 07735b0..731d1b6 100644 --- a/lib/src/subscription/client_subscription_impl.dart +++ b/lib/src/subscription/client_subscription_impl.dart @@ -51,7 +51,7 @@ final class SpinifyClientSubscriptionImpl extends SpinifyClientSubscriptionBase /// {@nodoc} @internal abstract base class SpinifyClientSubscriptionBase - implements SpinifyClientSubscription { + extends SpinifyClientSubscription { /// {@nodoc} SpinifyClientSubscriptionBase({ required this.channel, diff --git a/lib/src/subscription/client_subscription_manager.dart b/lib/src/subscription/client_subscription_manager.dart index 0968dc5..e809316 100644 --- a/lib/src/subscription/client_subscription_manager.dart +++ b/lib/src/subscription/client_subscription_manager.dart @@ -6,6 +6,7 @@ import 'package:spinify/src/model/exception.dart'; import 'package:spinify/src/subscription/client_subscription_impl.dart'; import 'package:spinify/src/subscription/subscription.dart'; import 'package:spinify/src/subscription/subscription_config.dart'; +import 'package:spinify/src/subscription/subscription_state.dart'; import 'package:spinify/src/transport/transport_interface.dart'; /// Responsible for managing client-side subscriptions. @@ -20,6 +21,28 @@ final class ClientSubscriptionManager { /// {@nodoc} final WeakReference _transportWeakRef; + /// Subscriptions count. + ({int total, int unsubscribed, int subscribing, int subscribed}) get count { + var total = 0, unsubscribed = 0, subscribing = 0, subscribed = 0; + for (final entry in _channelSubscriptions.values) { + total++; + switch (entry.state) { + case SpinifySubscriptionState$Unsubscribed _: + unsubscribed++; + case SpinifySubscriptionState$Subscribing _: + subscribing++; + case SpinifySubscriptionState$Subscribed _: + subscribed++; + } + } + return ( + total: total, + unsubscribed: unsubscribed, + subscribing: subscribing, + subscribed: subscribed, + ); + } + /// Subscriptions registry (channel -> subscription). /// Channel : SpinifyClientSubscription /// {@nodoc} diff --git a/lib/src/subscription/server_subscription_impl.dart b/lib/src/subscription/server_subscription_impl.dart index 38f11cf..555098e 100644 --- a/lib/src/subscription/server_subscription_impl.dart +++ b/lib/src/subscription/server_subscription_impl.dart @@ -48,7 +48,7 @@ final class SpinifyServerSubscriptionImpl extends SpinifyServerSubscriptionBase /// {@nodoc} @internal abstract base class SpinifyServerSubscriptionBase - implements SpinifyServerSubscription { + extends SpinifyServerSubscription { /// {@nodoc} SpinifyServerSubscriptionBase({ required this.channel, diff --git a/lib/src/subscription/server_subscription_manager.dart b/lib/src/subscription/server_subscription_manager.dart index 414bc25..a679981 100644 --- a/lib/src/subscription/server_subscription_manager.dart +++ b/lib/src/subscription/server_subscription_manager.dart @@ -6,6 +6,7 @@ import 'package:spinify/src/model/subscribe.dart'; import 'package:spinify/src/model/unsubscribe.dart'; import 'package:spinify/src/subscription/server_subscription_impl.dart'; import 'package:spinify/src/subscription/subscription.dart'; +import 'package:spinify/src/subscription/subscription_state.dart'; import 'package:spinify/src/transport/transport_interface.dart'; /// Responsible for managing client-side subscriptions. @@ -20,6 +21,28 @@ final class ServerSubscriptionManager { /// {@nodoc} final WeakReference _transportWeakRef; + /// Subscriptions count. + ({int total, int unsubscribed, int subscribing, int subscribed}) get count { + var total = 0, unsubscribed = 0, subscribing = 0, subscribed = 0; + for (final entry in _channelSubscriptions.values) { + total++; + switch (entry.state) { + case SpinifySubscriptionState$Unsubscribed _: + unsubscribed++; + case SpinifySubscriptionState$Subscribing _: + subscribing++; + case SpinifySubscriptionState$Subscribed _: + subscribed++; + } + } + return ( + total: total, + unsubscribed: unsubscribed, + subscribing: subscribing, + subscribed: subscribed, + ); + } + /// Subscriptions registry (channel -> subscription). /// Channel : SpinifyClientSubscription /// {@nodoc} diff --git a/lib/src/subscription/subscription.dart b/lib/src/subscription/subscription.dart index 6a3ca96..deee860 100644 --- a/lib/src/subscription/subscription.dart +++ b/lib/src/subscription/subscription.dart @@ -36,7 +36,7 @@ import 'package:spinify/src/subscription/subscription_states_stream.dart'; /// - For server-side subscriptions see [SpinifyServerSubscription]. /// {@endtemplate} /// {@category Subscription} -abstract interface class SpinifySubscription { +sealed class SpinifySubscription { /// Channel name. abstract final String channel; @@ -129,8 +129,7 @@ abstract interface class SpinifySubscription { /// {@endtemplate} /// {@category Subscription} /// {@subCategory Client-side} -abstract interface class SpinifyClientSubscription - implements SpinifySubscription { +abstract class SpinifyClientSubscription extends SpinifySubscription { /// Start subscribing to a channel Future subscribe(); @@ -155,5 +154,4 @@ abstract interface class SpinifyClientSubscription /// {@endtemplate} /// {@category Subscription} /// {@subCategory Server-side} -abstract interface class SpinifyServerSubscription - implements SpinifySubscription {} +abstract class SpinifyServerSubscription extends SpinifySubscription {}