@@ -20,8 +20,13 @@ public final class RealtimeClientV2: Sendable {
2020 var accessToken : String ?
2121 var ref = 0
2222 var pendingHeartbeatRef : Int ?
23+
24+ /// Long-running task that keeps sending heartbeat messages.
2325 var heartbeatTask : Task < Void , Never > ?
26+
27+ /// Long-running task for listening for incoming messages from WebSocket.
2428 var messageTask : Task < Void , Never > ?
29+
2530 var connectionTask : Task < Void , Never > ?
2631 var channels : [ String : RealtimeChannelV2 ] = [ : ]
2732 var sendBuffer : [ @Sendable ( ) async -> Void ] = [ ]
@@ -34,13 +39,14 @@ public final class RealtimeClientV2: Sendable {
3439 let http : any HTTPClientType
3540 let apikey : String ?
3641
42+ /// All managed channels indexed by their topics.
3743 public var channels : [ String : RealtimeChannelV2 ] {
3844 mutableState. channels
3945 }
4046
4147 private let statusEventEmitter = EventEmitter < RealtimeClientStatus > ( initialEvent: . disconnected)
4248
43- /// AsyncStream that emits when connection status change .
49+ /// Listen for connection status changes .
4450 ///
4551 /// You can also use ``onStatusChange(_:)`` for a closure based method.
4652 public var statusChange : AsyncStream < RealtimeClientStatus > {
@@ -198,6 +204,13 @@ public final class RealtimeClientV2: Sendable {
198204 await connect ( reconnect: true )
199205 }
200206
207+ /// Creates a new channel and bind it to this client.
208+ /// - Parameters:
209+ /// - topic: Channel's topic.
210+ /// - options: Configuration options for the channel.
211+ /// - Returns: Channel instance.
212+ ///
213+ /// - Note: This method doesn't subscribe to the channel, call ``RealtimeChannelV2/subscribe()`` on the returned channel instance.
201214 public func channel(
202215 _ topic: String ,
203216 options: @Sendable ( inout RealtimeChannelConfig ) -> Void = { _ in }
@@ -223,6 +236,9 @@ public final class RealtimeClientV2: Sendable {
223236 }
224237 }
225238
239+ /// Unsubscribe and removes channel.
240+ ///
241+ /// If there is no channel left, client is disconnected.
226242 public func removeChannel( _ channel: RealtimeChannelV2 ) async {
227243 if channel. status == . subscribed {
228244 await channel. unsubscribe ( )
@@ -238,6 +254,7 @@ public final class RealtimeClientV2: Sendable {
238254 }
239255 }
240256
257+ /// Unsubscribes and removes all channels.
241258 public func removeAllChannels( ) async {
242259 await withTaskGroup ( of: Void . self) { group in
243260 for channel in channels. values {
@@ -327,15 +344,19 @@ public final class RealtimeClientV2: Sendable {
327344 }
328345 }
329346
330- public func disconnect( ) {
347+ /// Disconnects client.
348+ /// - Parameters:
349+ /// - code: A numeric status code to send on disconnect.
350+ /// - reason: A custom reason for the disconnect.
351+ public func disconnect( code: Int ? = nil , reason: String ? = nil ) {
331352 options. logger? . debug ( " Closing WebSocket connection " )
332353 mutableState. withValue {
333354 $0. ref = 0
334355 $0. messageTask? . cancel ( )
335356 $0. heartbeatTask? . cancel ( )
336357 $0. connectionTask? . cancel ( )
337358 }
338- ws. disconnect ( )
359+ ws. disconnect ( code : code , reason : reason )
339360 status = . disconnected
340361 }
341362
@@ -388,13 +409,14 @@ public final class RealtimeClientV2: Sendable {
388409 try Task . checkCancellation ( )
389410 try await self ? . ws. send ( message)
390411 } catch {
391- self ? . options. logger? . error ( """
392- Failed to send message:
393- \( message)
394-
395- Error:
396- \( error)
397- """ )
412+ self ? . options. logger? . error (
413+ """
414+ Failed to send message:
415+ \( message)
416+
417+ Error:
418+ \( error)
419+ """ )
398420 }
399421 }
400422
0 commit comments