Skip to content

Commit 8fef76f

Browse files
Extract operations' channel state validation to helper
Code largely generated by Cursor at my request.
1 parent 36d76a2 commit 8fef76f

5 files changed

Lines changed: 31 additions & 48 deletions

File tree

Sources/AblyLiveObjects/Internal/CoreSDK.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,28 @@ internal final class DefaultCoreSDK: CoreSDK {
4040
channel.state
4141
}
4242
}
43+
44+
// MARK: - Channel State Validation
45+
46+
/// Extension on CoreSDK to provide channel state validation utilities.
47+
internal extension CoreSDK {
48+
/// Validates that the channel is not in any of the specified invalid states.
49+
///
50+
/// - Parameters:
51+
/// - invalidStates: Array of channel states that are considered invalid for the operation
52+
/// - operationDescription: A description of the operation being performed, used in error messages
53+
/// - Throws: `ARTErrorInfo` with code 90001 and statusCode 400 if the channel is in any of the invalid states
54+
func validateChannelState(
55+
notIn invalidStates: [ARTRealtimeChannelState],
56+
operationDescription: String,
57+
) throws(ARTErrorInfo) {
58+
let currentChannelState = channelState
59+
if invalidStates.contains(currentChannelState) {
60+
throw LiveObjectsError.objectsOperationFailedInvalidChannelState(
61+
operationDescription: operationDescription,
62+
channelState: currentChannelState,
63+
)
64+
.toARTErrorInfo()
65+
}
66+
}
67+
}

Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,7 @@ internal final class InternalDefaultLiveCounter: Sendable {
8181

8282
internal func value(coreSDK: CoreSDK) throws(ARTErrorInfo) -> Double {
8383
// RTLC5b: If the channel is in the DETACHED or FAILED state, the library should indicate an error with code 90001
84-
let currentChannelState = coreSDK.channelState
85-
if currentChannelState == .detached || currentChannelState == .failed {
86-
throw LiveObjectsError.objectsOperationFailedInvalidChannelState(
87-
operationDescription: "LiveCounter.value",
88-
channelState: currentChannelState,
89-
)
90-
.toARTErrorInfo()
91-
}
84+
try coreSDK.validateChannelState(notIn: [.detached, .failed], operationDescription: "LiveCounter.value")
9285

9386
return mutex.withLock {
9487
// RTLC5c

Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,7 @@ internal final class InternalDefaultLiveMap: Sendable {
111111
/// Returns the value associated with a given key, following RTLM5d specification.
112112
internal func get(key: String, coreSDK: CoreSDK, delegate: LiveMapObjectPoolDelegate) throws(ARTErrorInfo) -> InternalLiveMapValue? {
113113
// RTLM5c: If the channel is in the DETACHED or FAILED state, the library should indicate an error with code 90001
114-
let currentChannelState = coreSDK.channelState
115-
if currentChannelState == .detached || currentChannelState == .failed {
116-
throw LiveObjectsError.objectsOperationFailedInvalidChannelState(
117-
operationDescription: "LiveMap.get",
118-
channelState: currentChannelState,
119-
)
120-
.toARTErrorInfo()
121-
}
114+
try coreSDK.validateChannelState(notIn: [.detached, .failed], operationDescription: "LiveMap.get")
122115

123116
let entry = mutex.withLock {
124117
mutableState.data[key]
@@ -135,14 +128,7 @@ internal final class InternalDefaultLiveMap: Sendable {
135128

136129
internal func size(coreSDK: CoreSDK) throws(ARTErrorInfo) -> Int {
137130
// RTLM10c: If the channel is in the DETACHED or FAILED state, the library should throw an ErrorInfo error with statusCode 400 and code 90001
138-
let currentChannelState = coreSDK.channelState
139-
if currentChannelState == .detached || currentChannelState == .failed {
140-
throw LiveObjectsError.objectsOperationFailedInvalidChannelState(
141-
operationDescription: "LiveMap.size",
142-
channelState: currentChannelState,
143-
)
144-
.toARTErrorInfo()
145-
}
131+
try coreSDK.validateChannelState(notIn: [.detached, .failed], operationDescription: "LiveMap.size")
146132

147133
return mutex.withLock {
148134
// RTLM10d: Returns the number of non-tombstoned entries (per RTLM14) in the internal data map
@@ -154,14 +140,7 @@ internal final class InternalDefaultLiveMap: Sendable {
154140

155141
internal func entries(coreSDK: CoreSDK, delegate: LiveMapObjectPoolDelegate) throws(ARTErrorInfo) -> [(key: String, value: InternalLiveMapValue)] {
156142
// RTLM11c: If the channel is in the DETACHED or FAILED state, the library should throw an ErrorInfo error with statusCode 400 and code 90001
157-
let currentChannelState = coreSDK.channelState
158-
if currentChannelState == .detached || currentChannelState == .failed {
159-
throw LiveObjectsError.objectsOperationFailedInvalidChannelState(
160-
operationDescription: "LiveMap.entries",
161-
channelState: currentChannelState,
162-
)
163-
.toARTErrorInfo()
164-
}
143+
try coreSDK.validateChannelState(notIn: [.detached, .failed], operationDescription: "LiveMap.entries")
165144

166145
return mutex.withLock {
167146
// RTLM11d: Returns key-value pairs from the internal data map

Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
9393

9494
internal func getRoot(coreSDK: CoreSDK) async throws(ARTErrorInfo) -> InternalDefaultLiveMap {
9595
// RTO1b: If the channel is in the DETACHED or FAILED state, the library should indicate an error with code 90001
96-
let currentChannelState = coreSDK.channelState
97-
if currentChannelState == .detached || currentChannelState == .failed {
98-
throw LiveObjectsError.objectsOperationFailedInvalidChannelState(
99-
operationDescription: "getRoot",
100-
channelState: currentChannelState,
101-
)
102-
.toARTErrorInfo()
103-
}
96+
try coreSDK.validateChannelState(notIn: [.detached, .failed], operationDescription: "getRoot")
10497

10598
let syncStatus = mutex.withLock {
10699
mutableState.syncStatus

Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,7 @@ internal struct LiveObjectMutableState<Update: Sendable> {
8888
@discardableResult
8989
internal mutating func subscribe(listener: @escaping LiveObjectUpdateCallback<Update>, coreSDK: CoreSDK, updateSelfLater: @escaping UpdateLiveObject) throws(ARTErrorInfo) -> any AblyLiveObjects.SubscribeResponse {
9090
// RTLO4b2
91-
let currentChannelState = coreSDK.channelState
92-
if currentChannelState == .detached || currentChannelState == .failed {
93-
throw LiveObjectsError.objectsOperationFailedInvalidChannelState(
94-
operationDescription: "subscribe",
95-
channelState: currentChannelState,
96-
)
97-
.toARTErrorInfo()
98-
}
91+
try coreSDK.validateChannelState(notIn: [.detached, .failed], operationDescription: "subscribe")
9992

10093
let subscription = Subscription(listener: listener, updateLiveObject: updateSelfLater)
10194
subscriptionsByID[subscription.id] = subscription

0 commit comments

Comments
 (0)