Skip to content

Commit

Permalink
Fix leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev committed Dec 29, 2023
1 parent fb52244 commit c4e1910
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 15 deletions.
12 changes: 6 additions & 6 deletions Sources/Realtime/Channel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,9 @@ public final class RealtimeChannelV2: @unchecked Sendable {
continuation.yield($0)
}

continuation.onTermination = { _ in
continuation.onTermination = { [weak callbackManager] _ in
debug("Removing presence callback with id: \(id)")
self.callbackManager.removeCallback(id: id)
callbackManager?.removeCallback(id: id)
}

return stream
Expand Down Expand Up @@ -321,9 +321,9 @@ public final class RealtimeChannelV2: @unchecked Sendable {
}
}

continuation.onTermination = { _ in
continuation.onTermination = { [weak callbackManager] _ in
debug("Removing postgres callback with id: \(id)")
self.callbackManager.removeCallback(id: id)
callbackManager?.removeCallback(id: id)
}

return stream
Expand All @@ -338,9 +338,9 @@ public final class RealtimeChannelV2: @unchecked Sendable {
continuation.yield($0)
}

continuation.onTermination = { _ in
continuation.onTermination = { [weak callbackManager] _ in
debug("Removing broadcast callback with id: \(id)")
self.callbackManager.removeCallback(id: id)
callbackManager?.removeCallback(id: id)
}

return stream
Expand Down
12 changes: 6 additions & 6 deletions Sources/Realtime/RealtimeChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,9 @@ public class RealtimeChannel {
///
/// - parameter msg: The Message received by the client from the server
/// - return: Must return the message, modified or unmodified
// public var onMessage: (_ message: RealtimeMessage) -> RealtimeMessage = { message in
// message
// }
public var onMessage: (_ message: RealtimeMessage) -> RealtimeMessage = { message in
message
}

/// Joins the channel
///
Expand Down Expand Up @@ -852,9 +852,9 @@ public class RealtimeChannel {
/// - parameter payload: The payload for the message
/// - parameter ref: The reference of the message
/// - return: Must return the payload, modified or unmodified
// public func onMessage(callback: @escaping (RealtimeMessage) -> RealtimeMessage) {
// onMessage = callback
// }
public func onMessage(callback: @escaping (RealtimeMessage) -> RealtimeMessage) {
onMessage = callback
}

// ----------------------------------------------------------------------

Expand Down
1 change: 1 addition & 0 deletions Sources/Realtime/RealtimeClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct StateChangeCallbacks {
/// The `RealtimeClient` constructor takes the mount point of the socket,
/// the authentication params, as well as options that can be found in
/// the Socket docs, such as configuring the heartbeat.
@available(*, deprecated, message: "Use new Realtime class instead.")
public class RealtimeClient: PhoenixTransportDelegate {
// ----------------------------------------------------------------------

Expand Down
9 changes: 6 additions & 3 deletions Sources/Realtime/WebSocketClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ final class WebSocketClient: NSObject, URLSessionWebSocketDelegate, WebSocketCli
}

func cancel() {
mutableState.task?.cancel()
mutableState.withValue {
$0.task?.cancel()
$0.statusContinuation?.finish()
}
}

func urlSession(
Expand All @@ -74,7 +77,7 @@ final class WebSocketClient: NSObject, URLSessionWebSocketDelegate, WebSocketCli
mutableState.statusContinuation?.yield(.open)
}

nonisolated func urlSession(
func urlSession(
_: URLSession,
webSocketTask _: URLSessionWebSocketTask,
didCloseWith _: URLSessionWebSocketTask.CloseCode,
Expand All @@ -83,7 +86,7 @@ final class WebSocketClient: NSObject, URLSessionWebSocketDelegate, WebSocketCli
mutableState.statusContinuation?.yield(.close)
}

nonisolated func urlSession(
func urlSession(
_: URLSession,
task _: URLSessionTask,
didCompleteWithError error: Error?
Expand Down
16 changes: 16 additions & 0 deletions Tests/RealtimeTests/CallbackManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import XCTest
final class CallbackManagerTests: XCTestCase {
func testIntegration() {
let callbackManager = CallbackManager()
XCTAssertNoLeak(callbackManager)

let filter = PostgresJoinConfig(
event: .update,
schema: "public",
Expand Down Expand Up @@ -48,6 +50,8 @@ final class CallbackManagerTests: XCTestCase {

func testSetServerChanges() {
let callbackManager = CallbackManager()
XCTAssertNoLeak(callbackManager)

let changes = [PostgresJoinConfig(
event: .update,
schema: "public",
Expand All @@ -63,6 +67,8 @@ final class CallbackManagerTests: XCTestCase {

func testTriggerPostgresChanges() {
let callbackManager = CallbackManager()
XCTAssertNoLeak(callbackManager)

let updateUsersFilter = PostgresJoinConfig(
event: .update,
schema: "public",
Expand Down Expand Up @@ -165,6 +171,8 @@ final class CallbackManagerTests: XCTestCase {

func testTriggerBroadcast() {
let callbackManager = CallbackManager()
XCTAssertNoLeak(callbackManager)

let event = "new_user"
let message = RealtimeMessageV2(
joinRef: nil,
Expand Down Expand Up @@ -212,3 +220,11 @@ final class CallbackManagerTests: XCTestCase {
XCTAssertEqual(receivedAction.value?.leaves.count, 1)
}
}

extension XCTestCase {
func XCTAssertNoLeak(_ object: AnyObject, file: StaticString = #file, line: UInt = #line) {
addTeardownBlock { [weak object] in
XCTAssertNil(object, file: file, line: line)
}
}
}
12 changes: 12 additions & 0 deletions Tests/RealtimeTests/RealtimeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ final class RealtimeTests: XCTestCase {
makeWebSocketClient: { _ in mock }
)

XCTAssertNoLeak(realtime)

try await realtime.connect()

XCTAssertEqual(realtime.status, .connected)
Expand All @@ -34,8 +36,10 @@ final class RealtimeTests: XCTestCase {
config: Realtime.Configuration(url: url, apiKey: apiKey, authTokenProvider: nil),
makeWebSocketClient: { _ in mock }
)
XCTAssertNoLeak(realtime)

let channel = realtime.channel("users")
XCTAssertNoLeak(channel)

let changes = channel.postgresChange(
AnyAction.self,
Expand Down Expand Up @@ -126,5 +130,13 @@ final class RealtimeTests: XCTestCase {

let receivedChange = await receivedPostgresChangeTask.value
XCTAssertNoDifference(receivedChange, action)

try await channel.unsubscribe()

mock.mockReceive(
RealtimeMessageV2(joinRef: nil, ref: nil, topic: "realtime:users", event: ChannelEvent.leave, payload: [:])
)

await Task.megaYield()
}
}

0 comments on commit c4e1910

Please sign in to comment.