@@ -987,7 +987,7 @@ extension ClusterSystem {
987987 let recipient = _RemoteClusterActorPersonality < InvocationMessage > ( shell: clusterShell, id: actor . id. _asRemote, system: self )
988988 let arguments = invocation. arguments
989989
990- let reply : RemoteCallReply < Res > = try await self . withCallID { callID in
990+ let reply : RemoteCallReply < Res > = try await self . withCallID ( on : actor . id , target : target ) { callID in
991991 let invocation = InvocationMessage (
992992 callID: callID,
993993 targetIdentifier: target. identifier,
@@ -1022,7 +1022,7 @@ extension ClusterSystem {
10221022 let recipient = _RemoteClusterActorPersonality < InvocationMessage > ( shell: clusterShell, id: actor . id. _asRemote, system: self )
10231023 let arguments = invocation. arguments
10241024
1025- let reply : RemoteCallReply < _Done > = try await self . withCallID { callID in
1025+ let reply : RemoteCallReply < _Done > = try await self . withCallID ( on : actor . id , target : target ) { callID in
10261026 let invocation = InvocationMessage (
10271027 callID: callID,
10281028 targetIdentifier: target. identifier,
@@ -1037,22 +1037,44 @@ extension ClusterSystem {
10371037 }
10381038
10391039 private func withCallID< Reply> (
1040+ on actorID: ActorID ,
1041+ target: RemoteCallTarget ,
10401042 body: ( CallID ) -> Void
10411043 ) async throws -> Reply
10421044 where Reply: AnyRemoteCallReply
10431045 {
10441046 let callID = UUID ( )
10451047
10461048 let timeout = RemoteCall . timeout ?? self . settings. defaultRemoteCallTimeout
1047- let timeoutTask : Task < Void , Error > = Task {
1049+ let timeoutTask : Task < Void , Error > = Task . detached {
10481050 await Task . sleep ( UInt64 ( timeout. nanoseconds) )
10491051 guard !Task. isCancelled else {
10501052 return
10511053 }
1054+
10521055 self . inFlightCallLock. withLockVoid {
1053- if let continuation = self . _inFlightCalls. removeValue ( forKey: callID) {
1054- continuation. resume ( throwing: RemoteCallError . timedOut ( TimeoutError ( message: " Remote call timed out " , timeout: timeout) ) )
1056+ guard let continuation = self . _inFlightCalls. removeValue ( forKey: callID) else {
1057+ // remoteCall was already completed successfully, nothing to do here
1058+ return
10551059 }
1060+
1061+ let error : Error
1062+ if self . isShuttingDown {
1063+ // If the system is shutting down, we should offer a more specific error;
1064+ //
1065+ // We may not be getting responses simply because we've shut down associations
1066+ // and cannot receive them anymore.
1067+ // Some subsystems may ignore those errors, since they are "expected".
1068+ //
1069+ // If we're shutting down, it is okay to not get acknowledgements to calls for example,
1070+ // and we don't care about them missing -- we're shutting down anyway.
1071+ error = RemoteCallError . clusterAlreadyShutDown
1072+ } else {
1073+ error = RemoteCallError . timedOut (
1074+ TimeoutError ( message: " Remote call [ \( callID) ] to [ \( target) ]( \( actorID) ) timed out " , timeout: timeout) )
1075+ }
1076+
1077+ continuation. resume ( throwing: error)
10561078 }
10571079 }
10581080 defer {
0 commit comments