Skip to content

Commit 8073264

Browse files
committed
Support for concurrency and timers in chat
1 parent 822f519 commit 8073264

File tree

8 files changed

+24
-16
lines changed

8 files changed

+24
-16
lines changed

Sources/StreamCore/Concurrency/Atomic.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ public final class Atomic<T>: @unchecked Sendable {
5757
queue.sync { _value = changes(_value) }
5858
}
5959

60+
public func mutate(_ changes: (_ value: inout T) -> Void) {
61+
self.mutate { value in
62+
var updated = value
63+
changes(&updated)
64+
return updated
65+
}
66+
}
67+
6068
/// Update the value safely.
6169
/// - Parameter changes: a block with changes. It should return a new value.
6270
public func callAsFunction(_ changes: (_ value: T) -> T) { mutate(changes) }

Sources/StreamCore/Utils/Timers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import Combine
66
import Foundation
77

8-
public protocol StreamTimer {
8+
public protocol TimerScheduling {
99
/// Schedules a new timer.
1010
///
1111
/// - Parameters:
@@ -33,7 +33,7 @@ public protocol StreamTimer {
3333
static func currentTime() -> Date
3434
}
3535

36-
extension StreamTimer {
36+
extension TimerScheduling {
3737
public static func currentTime() -> Date {
3838
Date()
3939
}
@@ -58,7 +58,7 @@ extension DispatchWorkItem: TimerControl {}
5858
extension DispatchWorkItem: @retroactive @unchecked Sendable {}
5959

6060
/// Default real-world implementations of timers.
61-
public struct DefaultTimer: StreamTimer {
61+
public struct DefaultTimer: TimerScheduling {
6262
@discardableResult
6363
public static func schedule(
6464
timeInterval: TimeInterval,

Sources/StreamCore/WebSocket/Client/ConnectionRecoveryHandler.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public final class DefaultConnectionRecoveryHandler: ConnectionRecoveryHandler,
2424
private let eventNotificationCenter: EventNotificationCenter
2525
private let backgroundTaskScheduler: BackgroundTaskScheduler?
2626
private let internetConnection: InternetConnection
27-
private let reconnectionTimerType: StreamTimer.Type
27+
private let reconnectionTimerType: TimerScheduling.Type
2828
private let keepConnectionAliveInBackground: Bool
2929
private nonisolated(unsafe) var reconnectionStrategy: RetryStrategy
3030
private nonisolated(unsafe) var reconnectionTimer: TimerControl?
@@ -38,7 +38,7 @@ public final class DefaultConnectionRecoveryHandler: ConnectionRecoveryHandler,
3838
backgroundTaskScheduler: BackgroundTaskScheduler?,
3939
internetConnection: InternetConnection,
4040
reconnectionStrategy: RetryStrategy,
41-
reconnectionTimerType: StreamTimer.Type,
41+
reconnectionTimerType: TimerScheduling.Type,
4242
keepConnectionAliveInBackground: Bool
4343
) {
4444
self.init(
@@ -63,7 +63,7 @@ public final class DefaultConnectionRecoveryHandler: ConnectionRecoveryHandler,
6363
backgroundTaskScheduler: BackgroundTaskScheduler?,
6464
internetConnection: InternetConnection,
6565
reconnectionStrategy: RetryStrategy,
66-
reconnectionTimerType: StreamTimer.Type,
66+
reconnectionTimerType: TimerScheduling.Type,
6767
keepConnectionAliveInBackground: Bool,
6868
reconnectionPolicies: [AutomaticReconnectionPolicy]
6969
) {

Sources/StreamCore/WebSocket/Client/WebSocketClient.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public extension WebSocketClient {
158158
/// An object encapsulating all dependencies of `WebSocketClient`.
159159
struct Environment {
160160
typealias CreatePingController = (
161-
_ timerType: StreamTimer.Type,
161+
_ timerType: TimerScheduling.Type,
162162
_ timerQueue: DispatchQueue,
163163
_ webSocketClientType: WebSocketClientType
164164
) -> WebSocketPingController
@@ -169,7 +169,7 @@ public extension WebSocketClient {
169169
_ callbackQueue: DispatchQueue
170170
) -> WebSocketEngine
171171

172-
var timerType: StreamTimer.Type = DefaultTimer.self
172+
var timerType: TimerScheduling.Type = DefaultTimer.self
173173

174174
var createPingController: CreatePingController = WebSocketPingController.init
175175

@@ -186,7 +186,7 @@ public extension WebSocketClient {
186186
public init() {}
187187

188188
init(
189-
timerType: StreamTimer.Type = DefaultTimer.self,
189+
timerType: TimerScheduling.Type = DefaultTimer.self,
190190
createPingController: @escaping CreatePingController,
191191
createEngine: @escaping CreateEngine,
192192
eventBatcherBuilder: @escaping (

Sources/StreamCore/WebSocket/Client/WebSocketPingController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class WebSocketPingController {
2626
/// The time interval for pong timeout.
2727
static let pongTimeoutTimeInterval: TimeInterval = 3
2828

29-
private let timerType: StreamTimer.Type
29+
private let timerType: TimerScheduling.Type
3030
private let timerQueue: DispatchQueue
3131

3232
/// The timer used for scheduling `ping` calls
@@ -51,7 +51,7 @@ class WebSocketPingController {
5151
/// - timerType: a timer type.
5252
/// - timerQueue: a timer dispatch queue.
5353
init(
54-
timerType: StreamTimer.Type,
54+
timerType: TimerScheduling.Type,
5555
timerQueue: DispatchQueue,
5656
webSocketClientType: WebSocketClientType
5757
) {

Sources/StreamCore/WebSocket/Events/EventBatcher.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ protocol EventBatcher: Sendable {
1313
var currentBatch: Batch { get }
1414

1515
/// Creates new batch processor.
16-
init(period: TimeInterval, timerType: StreamTimer.Type, handler: @escaping BatchHandler)
16+
init(period: TimeInterval, timerType: TimerScheduling.Type, handler: @escaping BatchHandler)
1717

1818
/// Adds the item to the current batch of events. If it's the first event also schedules batch processing
1919
/// that will happen when `period` has passed.
@@ -29,7 +29,7 @@ class Batcher<Item>: @unchecked Sendable {
2929
/// The batching period. If the item is added sonner then `period` has passed after the first item they will get into the same batch.
3030
private let period: TimeInterval
3131
/// The time used to create timers.
32-
private let timerType: StreamTimer.Type
32+
private let timerType: TimerScheduling.Type
3333
/// The timer that calls `processor` when fired.
3434
private let batchProcessingTimer = AllocatedUnfairLock<TimerControl?>(nil)
3535
/// The closure which processes the batch.
@@ -41,7 +41,7 @@ class Batcher<Item>: @unchecked Sendable {
4141

4242
init(
4343
period: TimeInterval,
44-
timerType: StreamTimer.Type = DefaultTimer.self,
44+
timerType: TimerScheduling.Type = DefaultTimer.self,
4545
handler: @Sendable @escaping (_ batch: [Item], _ completion: @Sendable @escaping () -> Void) -> Void
4646
) {
4747
self.period = max(period, 0)

Tests/StreamCoreTests/Mocks/EventBatcher_Mock.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ final class EventBatcher_Mock: Batcher<Event>, @unchecked Sendable {
1010

1111
override init(
1212
period: TimeInterval = 0,
13-
timerType: StreamTimer.Type = DefaultTimer.self,
13+
timerType: TimerScheduling.Type = DefaultTimer.self,
1414
handler: @escaping @Sendable (_ batch: [Event], _ completion: @escaping @Sendable () -> Void) -> Void
1515
) {
1616
self.handler = handler

Tests/StreamCoreTests/TestUtils/VirtualTime/VirtualTimer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import Foundation
66
@testable import StreamCore
77

8-
struct VirtualTimeTimer: StreamTimer {
8+
struct VirtualTimeTimer: TimerScheduling {
99
nonisolated(unsafe) static var time: VirtualTime!
1010

1111
static func invalidate() {

0 commit comments

Comments
 (0)