Skip to content

Commit 14c590d

Browse files
authored
fix(realtime): Set default heartbeat interval to 25s (#667)
* fix * fix(realtime): Set default heartbeat interval to 25s
1 parent 660f709 commit 14c590d

File tree

6 files changed

+72
-29
lines changed

6 files changed

+72
-29
lines changed

Sources/Realtime/RealtimeClientV2.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import Helpers
1616
public typealias JSONObject = Helpers.JSONObject
1717

1818
/// Factory function for returning a new WebSocket connection.
19-
typealias WebSocketTransport = @Sendable () async throws -> any WebSocket
19+
typealias WebSocketTransport = @Sendable (_ url: URL, _ headers: [String: String]) async throws ->
20+
any WebSocket
2021

2122
public final class RealtimeClientV2: Sendable {
2223
struct MutableState {
@@ -93,14 +94,11 @@ public final class RealtimeClientV2: Sendable {
9394
self.init(
9495
url: url,
9596
options: options,
96-
wsTransport: {
97+
wsTransport: { url, headers in
9798
let configuration = URLSessionConfiguration.default
98-
configuration.httpAdditionalHeaders = options.headers.dictionary
99+
configuration.httpAdditionalHeaders = headers
99100
return try await URLSessionWebSocket.connect(
100-
to: Self.realtimeWebSocketURL(
101-
baseURL: Self.realtimeBaseURL(url: url),
102-
apikey: options.apikey
103-
),
101+
to: url,
104102
configuration: configuration
105103
)
106104
},
@@ -172,7 +170,14 @@ public final class RealtimeClientV2: Sendable {
172170
status = .connecting
173171

174172
do {
175-
let conn = try await wsTransport()
173+
let conn = try await wsTransport(
174+
Self.realtimeWebSocketURL(
175+
baseURL: Self.realtimeBaseURL(url: url),
176+
apikey: options.apikey,
177+
logLevel: options.logLevel
178+
),
179+
options.headers.dictionary
180+
)
176181
mutableState.withValue { $0.conn = conn }
177182
onConnected(reconnect: reconnect)
178183
} catch {
@@ -528,7 +533,7 @@ public final class RealtimeClientV2: Sendable {
528533
return url
529534
}
530535

531-
static func realtimeWebSocketURL(baseURL: URL, apikey: String?) -> URL {
536+
static func realtimeWebSocketURL(baseURL: URL, apikey: String?, logLevel: LogLevel?) -> URL {
532537
guard var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)
533538
else {
534539
return baseURL
@@ -540,6 +545,10 @@ public final class RealtimeClientV2: Sendable {
540545
}
541546
components.queryItems!.append(URLQueryItem(name: "vsn", value: "1.0.0"))
542547

548+
if let logLevel {
549+
components.queryItems!.append(URLQueryItem(name: "log_level", value: logLevel.rawValue))
550+
}
551+
543552
components.path.append("/websocket")
544553
components.path = components.path.replacingOccurrences(of: "//", with: "/")
545554

Sources/Realtime/Types.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ public struct RealtimeClientOptions: Sendable {
2121
var timeoutInterval: TimeInterval
2222
var disconnectOnSessionLoss: Bool
2323
var connectOnSubscribe: Bool
24+
25+
/// Sets the log level for Realtime
26+
var logLevel: LogLevel?
2427
var fetch: (@Sendable (_ request: URLRequest) async throws -> (Data, URLResponse))?
2528
package var accessToken: (@Sendable () async throws -> String?)?
2629
package var logger: (any SupabaseLogger)?
2730

28-
public static let defaultHeartbeatInterval: TimeInterval = 15
31+
public static let defaultHeartbeatInterval: TimeInterval = 25
2932
public static let defaultReconnectDelay: TimeInterval = 7
3033
public static let defaultTimeoutInterval: TimeInterval = 10
3134
public static let defaultDisconnectOnSessionLoss = true
@@ -38,6 +41,7 @@ public struct RealtimeClientOptions: Sendable {
3841
timeoutInterval: TimeInterval = Self.defaultTimeoutInterval,
3942
disconnectOnSessionLoss: Bool = Self.defaultDisconnectOnSessionLoss,
4043
connectOnSubscribe: Bool = Self.defaultConnectOnSubscribe,
44+
logLevel: LogLevel? = nil,
4145
fetch: (@Sendable (_ request: URLRequest) async throws -> (Data, URLResponse))? = nil,
4246
accessToken: (@Sendable () async throws -> String?)? = nil,
4347
logger: (any SupabaseLogger)? = nil
@@ -48,6 +52,7 @@ public struct RealtimeClientOptions: Sendable {
4852
self.timeoutInterval = timeoutInterval
4953
self.disconnectOnSessionLoss = disconnectOnSessionLoss
5054
self.connectOnSubscribe = connectOnSubscribe
55+
self.logLevel = logLevel
5156
self.fetch = fetch
5257
self.accessToken = accessToken
5358
self.logger = logger
@@ -84,3 +89,8 @@ public enum RealtimeClientStatus: Sendable, CustomStringConvertible {
8489
extension HTTPField.Name {
8590
static let apiKey = Self("apiKey")!
8691
}
92+
93+
/// Log level for Realtime.
94+
public enum LogLevel: String, Sendable {
95+
case info, warn, error
96+
}

Sources/TestHelpers/MockExtensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import InlineSnapshotTesting
1212
extension Mock {
1313
package func snapshotRequest(
1414
message: @autoclosure () -> String = "",
15-
record isRecording: Bool? = nil,
15+
record isRecording: SnapshotTestingConfiguration.Record? = nil,
1616
timeout: TimeInterval = 5,
1717
syntaxDescriptor: InlineSnapshotSyntaxDescriptor = InlineSnapshotSyntaxDescriptor(),
1818
matches expected: (() -> String)? = nil,

Supabase.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,17 @@
5959
"kind" : "remoteSourceControl",
6060
"location" : "https://github.com/apple/swift-asn1.git",
6161
"state" : {
62-
"revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6",
63-
"version" : "1.3.0"
62+
"revision" : "ae33e5941bb88d88538d0a6b19ca0b01e6c76dcf",
63+
"version" : "1.3.1"
6464
}
6565
},
6666
{
6767
"identity" : "swift-case-paths",
6868
"kind" : "remoteSourceControl",
6969
"location" : "https://github.com/pointfreeco/swift-case-paths",
7070
"state" : {
71-
"revision" : "bc92c4b27f9a84bfb498cdbfdf35d5a357e9161f",
72-
"version" : "1.5.6"
71+
"revision" : "19b7263bacb9751f151ec0c93ec816fe1ef67c7b",
72+
"version" : "1.6.1"
7373
}
7474
},
7575
{
@@ -95,17 +95,17 @@
9595
"kind" : "remoteSourceControl",
9696
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
9797
"state" : {
98-
"revision" : "163409ef7dae9d960b87f34b51587b6609a76c1f",
99-
"version" : "1.3.0"
98+
"revision" : "82a4ae7170d98d8538ec77238b7eb8e7199ef2e8",
99+
"version" : "1.3.1"
100100
}
101101
},
102102
{
103103
"identity" : "swift-crypto",
104104
"kind" : "remoteSourceControl",
105105
"location" : "https://github.com/apple/swift-crypto.git",
106106
"state" : {
107-
"revision" : "ff0f781cf7c6a22d52957e50b104f5768b50c779",
108-
"version" : "3.10.0"
107+
"revision" : "45305d32cfb830faebcaa9a7aea66ad342637518",
108+
"version" : "3.11.1"
109109
}
110110
},
111111
{
@@ -131,17 +131,17 @@
131131
"kind" : "remoteSourceControl",
132132
"location" : "https://github.com/pointfreeco/swift-identified-collections.git",
133133
"state" : {
134-
"revision" : "2f5ab6e091dd032b63dacbda052405756010dc3b",
135-
"version" : "1.1.0"
134+
"revision" : "322d9ffeeba85c9f7c4984b39422ec7cc3c56597",
135+
"version" : "1.1.1"
136136
}
137137
},
138138
{
139139
"identity" : "swift-snapshot-testing",
140140
"kind" : "remoteSourceControl",
141141
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
142142
"state" : {
143-
"revision" : "42a086182681cf661f5c47c9b7dc3931de18c6d7",
144-
"version" : "1.17.6"
143+
"revision" : "b2d4cb30735f4fbc3a01963a9c658336dd21e9ba",
144+
"version" : "1.18.1"
145145
}
146146
},
147147
{
@@ -167,8 +167,8 @@
167167
"kind" : "remoteSourceControl",
168168
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
169169
"state" : {
170-
"revision" : "a3f634d1a409c7979cabc0a71b3f26ffa9fc8af1",
171-
"version" : "1.4.3"
170+
"revision" : "b444594f79844b0d6d76d70fbfb3f7f71728f938",
171+
"version" : "1.5.1"
172172
}
173173
}
174174
],

Tests/RealtimeTests/RealtimeTests.swift

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import XCTest
1414

1515
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
1616
final class RealtimeTests: XCTestCase {
17-
let url = URL(string: "https://localhost:54321/realtime/v1")!
17+
let url = URL(string: "http://localhost:54321/realtime/v1")!
1818
let apiKey = "anon.api.key"
1919

2020
override func invokeTest() {
@@ -49,7 +49,7 @@ final class RealtimeTests: XCTestCase {
4949
"custom.access.token"
5050
}
5151
),
52-
wsTransport: { self.client },
52+
wsTransport: { _, _ in self.client },
5353
http: http
5454
)
5555
}
@@ -60,6 +60,30 @@ final class RealtimeTests: XCTestCase {
6060
super.tearDown()
6161
}
6262

63+
func test_transport() async {
64+
let client = RealtimeClientV2(
65+
url: url,
66+
options: RealtimeClientOptions(
67+
headers: ["apikey": apiKey],
68+
logLevel: .warn,
69+
accessToken: {
70+
"custom.access.token"
71+
}
72+
),
73+
wsTransport: { url, headers in
74+
assertInlineSnapshot(of: url, as: .description) {
75+
"""
76+
ws://localhost:54321/realtime/v1/websocket?apikey=anon.api.key&vsn=1.0.0&log_level=warn
77+
"""
78+
}
79+
return FakeWebSocket.fakes().0
80+
},
81+
http: http
82+
)
83+
84+
await client.connect()
85+
}
86+
6387
func testBehavior() async throws {
6488
let channel = sut.channel("public:messages")
6589
var subscriptions: Set<ObservationToken> = []
@@ -352,7 +376,7 @@ final class RealtimeTests: XCTestCase {
352376
let request = await http.receivedRequests.last
353377
assertInlineSnapshot(of: request?.urlRequest, as: .raw(pretty: true)) {
354378
"""
355-
POST https://localhost:54321/realtime/v1/api/broadcast
379+
POST http://localhost:54321/realtime/v1/api/broadcast
356380
Authorization: Bearer custom.access.token
357381
Content-Type: application/json
358382
apiKey: anon.api.key

Tests/RealtimeTests/_PushTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ final class _PushTests: XCTestCase {
3434
options: RealtimeClientOptions(
3535
headers: ["apiKey": "apikey"]
3636
),
37-
wsTransport: { client },
37+
wsTransport: { _, _ in client },
3838
http: HTTPClientMock()
3939
)
4040
}

0 commit comments

Comments
 (0)