You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add method for waiting to be able to do non-attach presence ops
This is needed for Umair to be able to implement the presence and typing
indicators spec points that I’ve mentioned in the code. Based on spec at
f7ca465.
Resolves#112.
Copy file name to clipboardExpand all lines: Sources/AblyChat/Errors.swift
+30-14Lines changed: 30 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -11,6 +11,8 @@ public let errorDomain = "AblyChatErrorDomain"
11
11
The error codes for errors in the ``errorDomain`` error domain.
12
12
*/
13
13
publicenumErrorCode:Int{
14
+
case nonspecific =40000
15
+
14
16
/// ``Rooms.get(roomID:options:)`` was called with a different set of room options than was used on a previous call. You must first release the existing room instance using ``Rooms.release(roomID:)``.
15
17
///
16
18
/// TODO this code is a guess, revisit in https://github.com/ably-labs/ably-chat-swift/issues/32
@@ -36,7 +38,8 @@ public enum ErrorCode: Int {
36
38
internalvarstatusCode:Int{
37
39
// TODO: These are currently a guess, revisit once outstanding spec question re status codes is answered (https://github.com/ably/specification/pull/200#discussion_r1755222945), and also revisit in https://github.com/ably-labs/ably-chat-swift/issues/32
38
40
switchself{
39
-
case.inconsistentRoomOptions,
41
+
case.nonspecific,
42
+
.inconsistentRoomOptions,
40
43
.messagesDetachmentFailed,
41
44
.presenceDetachmentFailed,
42
45
.reactionsDetachmentFailed,
@@ -69,6 +72,8 @@ internal enum ChatError {
69
72
case roomInFailedState
70
73
case roomIsReleasing
71
74
case roomIsReleased
75
+
case presenceOperationRequiresRoomAttach(feature:RoomFeature)
76
+
case presenceOperationDisallowedForCurrentRoomStatus(feature:RoomFeature)
72
77
73
78
/// The ``ARTErrorInfo.code`` that should be returned for this error.
74
79
internalvarcode:ErrorCode{
@@ -107,20 +112,14 @@ internal enum ChatError {
107
112
.roomIsReleasing
108
113
case.roomIsReleased:
109
114
.roomIsReleased
115
+
case.presenceOperationRequiresRoomAttach,
116
+
.presenceOperationDisallowedForCurrentRoomStatus:
117
+
.nonspecific
110
118
}
111
119
}
112
120
113
-
/// A helper type for parameterising the construction of error messages.
// TODO: Address force unwrapping of `channels` within feature initialisation below: https://github.com/ably-labs/ably-chat-swift/issues/105
97
99
98
100
messages =awaitDefaultMessages(
@@ -124,7 +126,12 @@ internal actor DefaultRoom<LifecycleManagerFactory: RoomLifecycleManagerFactory>
Copy file name to clipboardExpand all lines: Sources/AblyChat/RoomFeature.swift
+20-1Lines changed: 20 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -31,19 +31,38 @@ internal enum RoomFeature {
31
31
32
32
/// Provides all of the channel-related functionality that a room feature (e.g. an implementation of ``Messages``) needs.
33
33
///
34
-
/// This mishmash exists to give a room feature access to both:
34
+
/// This mishmash exists to give a room feature access to:
35
35
///
36
36
/// - a `RealtimeChannelProtocol` object (this is the interface that our features are currently written against, as opposed to, say, `RoomLifecycleContributorChannel`)
37
37
/// - the discontinuities emitted by the room lifecycle
38
+
/// - the presence-readiness wait mechanism supplied by the room lifecycle
/// Waits until we can perform presence operations on the contributors of this room without triggering an implicit attach.
43
+
///
44
+
/// Implements the checks described by CHA-PR3d, CHA-PR3e, CHA-PR3f, and CHA-PR3g (and similar ones described by other functionality that performs contributor presence operations). Namely:
45
+
///
46
+
/// - CHA-PR3d, CHA-PR10d, CHA-PR6c, CHA-T2c: If the room is in the ATTACHING status, it waits for the current ATTACH to complete and then returns. If the current ATTACH fails, then it re-throws that operation’s error.
47
+
/// - CHA-PR3e, CHA-PR11e, CHA-PR6d, CHA-T2d: If the room is in the ATTACHED status, it returns immediately.
48
+
/// - CHA-PR3f, CHA-PR11f, CHA-PR6e, CHA-T2e: If the room is in the DETACHED status, it throws an `ARTErrorInfo` derived from ``ChatError.presenceOperationRequiresRoomAttach(feature:)``.
49
+
/// - // CHA-PR3g, CHA-PR11g, CHA-PR6f, CHA-T2f: If the room is in any other status, it throws an `ARTErrorInfo` derived from ``ChatError.presenceOperationDisallowedForCurrentRoomStatus(feature:)``.
50
+
///
51
+
/// - Parameters:
52
+
/// - requester: The room feature that wishes to perform a presence operation. This is only used for customising the message of the thrown error.
@@ -556,7 +557,7 @@ internal actor DefaultRoomLifecycleManager<Contributor: RoomLifecycleContributor
556
557
/// The manager emits an `OperationWaitEvent` each time one room lifecycle operation is going to wait for another to complete. These events are emitted to support testing of the manager; see ``testsOnly_subscribeToOperationWaitEvents``.
557
558
internalstructOperationWaitEvent:Equatable{
558
559
/// The ID of the operation which initiated the wait. It is waiting for the operation with ID ``waitedOperationID`` to complete.
559
-
internalvarwaitingOperationID:UUID
560
+
internalvarwaitingOperationID:UUID?
560
561
/// The ID of the operation whose completion will be awaited.
561
562
internalvarwaitedOperationID:UUID
562
563
}
@@ -573,6 +574,29 @@ internal actor DefaultRoomLifecycleManager<Contributor: RoomLifecycleContributor
573
574
}
574
575
#endif
575
576
577
+
privateenumOperationWaitRequester{
578
+
case anotherOperation(operationID:UUID)
579
+
case waitToBeAbleToPerformPresenceOperations
580
+
581
+
internalvarloggingDescription:String{
582
+
switchself{
583
+
caselet.anotherOperation(operationID):
584
+
"Operation \(operationID)"
585
+
case.waitToBeAbleToPerformPresenceOperations:
586
+
"waitToBeAbleToPerformPresenceOperations"
587
+
}
588
+
}
589
+
590
+
internalvarwaitingOperationID:UUID?{
591
+
switchself{
592
+
caselet.anotherOperation(operationID):
593
+
operationID
594
+
case.waitToBeAbleToPerformPresenceOperations:
595
+
nil
596
+
}
597
+
}
598
+
}
599
+
576
600
/// Waits for the operation with ID `waitedOperationID` to complete, re-throwing any error thrown by that operation.
577
601
///
578
602
/// Note that this method currently treats all waited operations as throwing. If you wish to wait for an operation that you _know_ to be non-throwing (which the RELEASE operation currently is) then you’ll need to call this method with `try!` or equivalent. (It might be possible to improve this in the future, but I didn’t want to put much time into figuring it out.)
@@ -581,20 +605,20 @@ internal actor DefaultRoomLifecycleManager<Contributor: RoomLifecycleContributor
581
605
///
582
606
/// - Parameters:
583
607
/// - waitedOperationID: The ID of the operation whose completion will be awaited.
584
-
/// - waitingOperationID: The ID of the operation which is awaiting this result. Only used for logging.
608
+
/// - requester: A description of who is awaiting this result. Only used for logging.
585
609
privatefunc waitForCompletionOfOperationWithID(
586
610
_ waitedOperationID:UUID,
587
-
waitingOperationID:UUID
611
+
requester:OperationWaitRequester
588
612
)asyncthrows(ARTErrorInfo){
589
-
logger.log(message:"Operation \(waitingOperationID) started waiting for result of operation \(waitedOperationID)", level:.debug)
613
+
logger.log(message:"\(requester.loggingDescription) started waiting for result of operation \(waitedOperationID)", level:.debug)
// My “it is guaranteed” in the documentation for this method is really more of an “I hope that”, because it’s based on my pretty vague understanding of Swift concurrency concepts; namely, I believe that if you call this manager-isolated `async` method from another manager-isolated method, the initial synchronous part of this method — in particular the call to `addContinuation` below — will occur _before_ the call to this method suspends. (I think this can be roughly summarised as “calls to async methods on self don’t do actor hopping” but I could be completely misusing a load of Swift concurrency vocabulary there.)
@@ -603,9 +627,9 @@ internal actor DefaultRoomLifecycleManager<Contributor: RoomLifecycleContributor
603
627
604
628
try result.get()
605
629
606
-
logger.log(message:"Operation \(waitingOperationID) completed waiting for result of operation \(waitedOperationID), which completed successfully", level:.debug)
630
+
logger.log(message:"\(requester.loggingDescription) completed waiting for result of operation \(waitedOperationID), which completed successfully", level:.debug)
607
631
}catch{
608
-
logger.log(message:"Operation \(waitingOperationID) completed waiting for result of operation \(waitedOperationID), which threw error \(error)", level:.debug)
632
+
logger.log(message:"\(requester.loggingDescription) completed waiting for result of operation \(waitedOperationID), which threw error \(error)", level:.debug)
609
633
throw error
610
634
}
611
635
}
@@ -686,7 +710,7 @@ internal actor DefaultRoomLifecycleManager<Contributor: RoomLifecycleContributor
0 commit comments