@@ -20,8 +20,13 @@ public final class RealtimeClientV2: Sendable {
20
20
var accessToken : String ?
21
21
var ref = 0
22
22
var pendingHeartbeatRef : Int ?
23
+
24
+ /// Long-running task that keeps sending heartbeat messages.
23
25
var heartbeatTask : Task < Void , Never > ?
26
+
27
+ /// Long-running task for listening for incoming messages from WebSocket.
24
28
var messageTask : Task < Void , Never > ?
29
+
25
30
var connectionTask : Task < Void , Never > ?
26
31
var channels : [ String : RealtimeChannelV2 ] = [ : ]
27
32
var sendBuffer : [ @Sendable ( ) async -> Void ] = [ ]
@@ -34,13 +39,14 @@ public final class RealtimeClientV2: Sendable {
34
39
let http : any HTTPClientType
35
40
let apikey : String ?
36
41
42
+ /// All managed channels indexed by their topics.
37
43
public var channels : [ String : RealtimeChannelV2 ] {
38
44
mutableState. channels
39
45
}
40
46
41
47
private let statusEventEmitter = EventEmitter < RealtimeClientStatus > ( initialEvent: . disconnected)
42
48
43
- /// AsyncStream that emits when connection status change .
49
+ /// Listen for connection status changes .
44
50
///
45
51
/// You can also use ``onStatusChange(_:)`` for a closure based method.
46
52
public var statusChange : AsyncStream < RealtimeClientStatus > {
@@ -198,6 +204,13 @@ public final class RealtimeClientV2: Sendable {
198
204
await connect ( reconnect: true )
199
205
}
200
206
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.
201
214
public func channel(
202
215
_ topic: String ,
203
216
options: @Sendable ( inout RealtimeChannelConfig ) -> Void = { _ in }
@@ -223,6 +236,9 @@ public final class RealtimeClientV2: Sendable {
223
236
}
224
237
}
225
238
239
+ /// Unsubscribe and removes channel.
240
+ ///
241
+ /// If there is no channel left, client is disconnected.
226
242
public func removeChannel( _ channel: RealtimeChannelV2 ) async {
227
243
if channel. status == . subscribed {
228
244
await channel. unsubscribe ( )
@@ -238,6 +254,7 @@ public final class RealtimeClientV2: Sendable {
238
254
}
239
255
}
240
256
257
+ /// Unsubscribes and removes all channels.
241
258
public func removeAllChannels( ) async {
242
259
await withTaskGroup ( of: Void . self) { group in
243
260
for channel in channels. values {
@@ -327,15 +344,19 @@ public final class RealtimeClientV2: Sendable {
327
344
}
328
345
}
329
346
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 ) {
331
352
options. logger? . debug ( " Closing WebSocket connection " )
332
353
mutableState. withValue {
333
354
$0. ref = 0
334
355
$0. messageTask? . cancel ( )
335
356
$0. heartbeatTask? . cancel ( )
336
357
$0. connectionTask? . cancel ( )
337
358
}
338
- ws. disconnect ( )
359
+ ws. disconnect ( code : code , reason : reason )
339
360
status = . disconnected
340
361
}
341
362
@@ -388,13 +409,14 @@ public final class RealtimeClientV2: Sendable {
388
409
try Task . checkCancellation ( )
389
410
try await self ? . ws. send ( message)
390
411
} 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
+ """ )
398
420
}
399
421
}
400
422
0 commit comments