@@ -173,11 +173,11 @@ import _Concurrency
173
173
///
174
174
/// Implementing the remote calls correctly and efficiently is the important task for a distributed actor system library.
175
175
/// Since those methods are not currently expressible as protocol requirements due to advanced use of generics
176
- /// combined with type aliases , they will not appear in the protocol's documentation as explicit requirements.
176
+ /// combined with associated types , they will not appear in the protocol's documentation as explicit requirements.
177
177
/// Instead, we present their signatures that a conforming type has to implement here:
178
178
///
179
179
/// > Note: Although the `remoteCall` methods are not expressed as protocol requirements in source,
180
- /// > the compiler will provide the same errors as-if they were declared explicitly in this protocol.
180
+ /// > the compiler will provide the same errors as-if it was declared explicitly in this protocol.
181
181
///
182
182
/// ```swift
183
183
/// /// Invoked by the Swift runtime when making a remote call.
@@ -280,17 +280,24 @@ public protocol DistributedActorSystem: Sendable {
280
280
// ==== ---------------------------------------------------------------------
281
281
// - MARK: Resolving actors by identity
282
282
283
- /// Resolve a local or remote actor address to a real actor instance, or throw if unable to.
283
+ /// Resolves a local or remote ``ActorID`` to a reference to given actor, or throws if unable to.
284
+ ///
284
285
/// The returned value is either a local actor or proxy to a remote actor.
285
286
///
286
- /// Resolving an actor is called when a specific distributed actors `init(from:)`
287
- /// decoding initializer is invoked. Once the actor's identity is deserialized
288
- /// using the `decodeIdentity(from:)` call, it is fed into this function, which
289
- /// is responsible for resolving the identity to a remote or local actor reference.
287
+ /// This function is not intended to be used directly, but instead is called by the Swift runtime
288
+ /// whenever ``DistributedActor/resolve(id:using:)` or a concrete distributed actor's `init(from:)` is invoked.
289
+ ///
290
+ /// This function should either return an existing actor reference, or `nil` to signal that a remote distributed actor
291
+ /// "proxy" should be created for this ``ActorID``. If the resolve fails, meaning that it can neither locate a local
292
+ /// actor managed by this actor system, nor identify that the identity is located on some remote actor system, then
293
+ /// this function should throw.
294
+ ///
295
+ /// ```swift
296
+ /// distributed actor Worker { /* ... */ }
290
297
///
291
- /// If the resolve fails, meaning that it cannot locate a local actor managed for
292
- /// this identity, managed by this transport, nor can a remote actor reference
293
- /// be created for this identity on this transport, then this function must throw.
298
+ /// // the following internally calls actorSystem.resolve(id: id, as: Worker.self)
299
+ /// let worker: Worker = try Worker.resolve(id: id, using: actorSystem)
300
+ /// ```
294
301
///
295
302
/// If this function returns correctly, the returned actor reference is immediately
296
303
/// usable. It may not necessarily imply the strict *existence* of a remote actor
@@ -300,13 +307,20 @@ public protocol DistributedActorSystem: Sendable {
300
307
///
301
308
/// Detecting liveness of such remote actors shall be offered / by transport libraries
302
309
/// by other means, such as "watching an actor for termination" or similar.
310
+ ///
311
+ /// - Parameter id: The `ActorID` to resolve an actor reference for
312
+ /// - Parameter actorType: The type of distributed actor the ID is expected to point at.
313
+ ///
314
+ /// - Throws: When unable to confirm if the `id` is correct, the resolved actor does not match the expected `actorType`,
315
+ /// or any other internal validation error within the actor system's resolve process occurs.
303
316
func resolve< Act> ( id: ActorID , as actorType: Act . Type ) throws -> Act ?
304
317
where Act: DistributedActor ,
305
318
Act. ID == ActorID
306
319
307
320
// ==== ---------------------------------------------------------------------
308
321
// - MARK: Actor Lifecycle
309
- /// Create an `ActorID` for the passed actor type.
322
+
323
+ /// Assign an ``ActorID`` for the passed actor type.
310
324
///
311
325
/// This function is invoked by an distributed actor during its initialization,
312
326
/// and the returned address value is stored along with it for the time of its
@@ -326,10 +340,10 @@ public protocol DistributedActorSystem: Sendable {
326
340
/// mapping for the purpose of implementing the `resolve(id:as:)` method.
327
341
///
328
342
/// The system usually should NOT retain the passed reference, and it will be informed via
329
- /// `resignID(_:)` when the actor has been deallocated so it can remove the stale reference from its
343
+ /// `` resignID(_:)` ` when the actor has been deallocated so it can remove the stale reference from its
330
344
/// internal `ActorID: DistributedActor` mapping.
331
345
///
332
- /// The `actor. id` of the passed actor must be an `ActorID` that this system previously has assigned.
346
+ /// The ``DistributedActor/ id`` of the passed actor must be an `` ActorID` ` that this system previously has assigned.
333
347
///
334
348
/// If `actorReady` gets called with some unknown ID, it should crash immediately as it signifies some
335
349
/// very unexpected use of the system.
@@ -688,6 +702,32 @@ func _executeDistributedTarget<D: DistributedTargetInvocationDecoder>(
688
702
/// Once encoded, the system should use some underlying transport mechanism to send the
689
703
/// bytes serialized by the invocation to the remote peer.
690
704
///
705
+ /// ### Protocol requirements
706
+ /// Similar to the ``DistributedActorSystem`` and its `remoteCall` and `remoteCallVoid` protocol requirements,
707
+ /// the `DistributedTargetInvocationEncoder` contains a few methods which are not possible to express in source due to
708
+ /// advanced use of generics combined with associated types. Specifically, the `recordArgument` and `recordReturnType`
709
+ /// methods are not expressed in source as protocol requirements, but will be treated by the compiler as-if they were.
710
+ ///
711
+ /// > Note: Although the `recordArgument` method is not expressed as protocol requirement in source,
712
+ /// > the compiler will provide the same errors as-if it was declared explicitly in this protocol.
713
+ ///
714
+ /// In addition to the compiler offering compile errors if those witnesses are missing in an adopting type,
715
+ /// we present their signatures here for reference:
716
+ ///
717
+ /// ```swift
718
+ /// /// Record an argument of `Argument` type.
719
+ /// /// This will be invoked for every argument of the target, in declaration order.
720
+ /// mutating func recordArgument<Value: SerializationRequirement>(
721
+ /// _ argument: DistributedTargetArgument<Value>
722
+ /// ) throws
723
+ ///
724
+ /// /// Ad-hoc requirement
725
+ /// ///
726
+ /// /// Record the return type of the distributed method.
727
+ /// /// This method will not be invoked if the target is returning `Void`.
728
+ /// mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws
729
+ /// ```
730
+ ///
691
731
/// ## Decoding an invocation
692
732
/// Since every actor system is going to deal with a concrete invocation type, they may
693
733
/// implement decoding them whichever way is most optimal for the given system.
@@ -700,10 +740,13 @@ func _executeDistributedTarget<D: DistributedTargetInvocationDecoder>(
700
740
/// entry points on the provided types.
701
741
@available( SwiftStdlib 5.7 , * )
702
742
public protocol DistributedTargetInvocationEncoder {
743
+ /// The serialization requirement that the types passed to `recordArgument` and `recordReturnType` are required to conform to.
703
744
associatedtype SerializationRequirement
704
745
705
746
/// The arguments must be encoded order-preserving, and once `decodeGenericSubstitutions`
706
747
/// is called, the substitutions must be returned in the same order in which they were recorded.
748
+ ///
749
+ /// - Parameter type: a generic substitution type to be recorded for this invocation.
707
750
mutating func recordGenericSubstitution< T> ( _ type: T . Type ) throws
708
751
709
752
// /// Ad-hoc requirement
@@ -716,6 +759,8 @@ public protocol DistributedTargetInvocationEncoder {
716
759
717
760
/// Record the error type of the distributed method.
718
761
/// This method will not be invoked if the target is not throwing.
762
+ ///
763
+ /// - Parameter type: the type of error that was declared to be thrown by the invocation target. Currently this can only ever be `Error.self`.
719
764
mutating func recordErrorType< E: Error > ( _ type: E . Type ) throws
720
765
721
766
// /// Ad-hoc requirement
@@ -724,6 +769,10 @@ public protocol DistributedTargetInvocationEncoder {
724
769
// /// This method will not be invoked if the target is returning `Void`.
725
770
// mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws
726
771
772
+ /// Invoked to signal to the encoder that no further `record...` calls will be made on it.
773
+ ///
774
+ /// Useful if the encoder needs to perform some "final" task before the underlying message is considered complete,
775
+ /// e.g. computing a checksum, or some additional message signing or finalization step.
727
776
mutating func do neRecording( ) throws
728
777
}
729
778
@@ -771,10 +820,48 @@ public struct RemoteCallArgument<Value> {
771
820
772
821
/// Decoder that must be provided to `executeDistributedTarget` and is used
773
822
/// by the Swift runtime to decode arguments of the invocation.
823
+ ///
824
+ /// ### Protocol requirements
825
+ /// Similar to the ``DistributedTargetInvocationEncoder`` and its `recordArgument` and `recordReturnType` protocol requirements,
826
+ /// the `DistributedTargetInvocationDecoder` contains a method which is not possible to express in source due to
827
+ /// advanced use of generics combined with associated types. Specifically, the `decodeNextArgument`
828
+ /// method is not expressed in source as protocol requirement, but will be treated by the compiler as-if it was.
829
+ ///
830
+ /// > Note: Although the `decodeNextArgument` method is not expressed as protocol requirement in source,
831
+ /// > the compiler will provide the same errors as-if it was declared explicitly in this protocol.
832
+ ///
833
+ /// In addition to the compiler offering compile errors if this witness is missing in an adopting type,
834
+ /// we present its signature here for reference:
835
+ ///
836
+ /// ```swift
837
+ /// /// Ad-hoc protocol requirement
838
+ /// ///
839
+ /// /// Attempt to decode the next argument from the underlying buffers into pre-allocated storage
840
+ /// /// pointed at by 'pointer'.
841
+ /// ///
842
+ /// /// This method should throw if it has no more arguments available, if decoding the argument failed,
843
+ /// /// or, optionally, if the argument type we're trying to decode does not match the stored type.
844
+ /// ///
845
+ /// /// The result of the decoding operation must be stored into the provided 'pointer' rather than
846
+ /// /// returning a value. This pattern allows the runtime to use a heavily optimized, pre-allocated
847
+ /// /// buffer for all the arguments and their expected types. The 'pointer' passed here is a pointer
848
+ /// /// to a "slot" in that pre-allocated buffer. That buffer will then be passed to a thunk that
849
+ /// /// performs the actual distributed (local) instance method invocation.
850
+ /// mutating func decodeNextArgument<Argument: SerializationRequirement>() throws -> Argument
851
+ /// ```
774
852
@available ( SwiftStdlib 5 . 7 , * )
775
853
public protocol DistributedTargetInvocationDecoder {
854
+ /// The serialization requirement that the types passed to `decodeNextArgument` are required to conform to.
855
+ /// The type returned by `decodeReturnType` is also expected to conform to this associated type requirement.
776
856
associatedtype SerializationRequirement
777
857
858
+ /// Decode all generic substitutions that were recorded for this invocation.
859
+ ///
860
+ /// The values retrieved from here must be in the same order as they were recorded by
861
+ /// ``DistributedTargetInvocationEncoder/recordGenericSubstitution(_:)``.
862
+ ///
863
+ /// - Returns: array of all generic substitutions necessary to execute this invocation target.
864
+ /// - Throws: if decoding substitutions fails.
778
865
mutating func decodeGenericSubstitutions( ) throws -> [ Any . Type ]
779
866
780
867
// /// Ad-hoc protocol requirement
@@ -792,6 +879,10 @@ public protocol DistributedTargetInvocationDecoder {
792
879
// /// performs the actual distributed (local) instance method invocation.
793
880
// mutating func decodeNextArgument<Argument: SerializationRequirement>() throws -> Argument
794
881
882
+ /// Decode the specific error type that the distributed invocation target has recorded.
883
+ /// Currently this effectively can only ever be `Error.self`.
884
+ ///
885
+ /// If the target known to not be throwing, or no error type was recorded, the method should return `nil`.
795
886
mutating func decodeErrorType( ) throws -> Any . Type ?
796
887
797
888
/// Attempt to decode the known return type of the distributed invocation.
@@ -801,15 +892,51 @@ public protocol DistributedTargetInvocationDecoder {
801
892
mutating func decodeReturnType( ) throws -> Any . Type ?
802
893
}
803
894
895
+ /// Protocol a distributed invocation execution's result handler.
896
+ ///
897
+ /// An instance conforming to this type must be passed when invoking
898
+ /// ``executeDistributedTarget(on:target:invocationDecoder:handler:)`` while handling an incoming distributed call.
899
+ ///
900
+ /// The handler will then be invoked with the return value (or error) that the invoked target returned (or threw).
901
+ ///
902
+ /// ### Protocol requirements
903
+ /// Similar to the ``DistributedActorSystem`` and its `remoteCall` and `remoteCallVoid` protocol requirements,
904
+ /// the `DistributedTargetInvocationResultHandler` contains a method which is not possible to express in source due to
905
+ /// advanced use of generics combined with associated types. Specifically, the `onReturn` method is not expressed in
906
+ /// source as protocol requirement, but will be treated by the compiler as-if they were.
907
+ ///
908
+ /// > Note: Although the `onReturn` method is not expressed as protocol requirement in source,
909
+ /// > the compiler will provide the same errors as-if it was declared explicitly in this protocol.
910
+ ///
911
+ /// In addition to the compiler offering compile errors if this witnesses is missing in an adopting type,
912
+ /// we present its signature here for reference:
913
+ ///
914
+ /// ```swift
915
+ /// /// Ad-hoc protocol requirement
916
+ /// ///
917
+ /// /// Invoked when the distributed target execution returns successfully.
918
+ /// /// The `value` is the return value of the executed distributed invocation target.
919
+ /// func onReturn<Success: SerializationRequirement>(value: Success) async throws
920
+ /// ```
804
921
@available ( SwiftStdlib 5 . 7 , * )
805
922
public protocol DistributedTargetInvocationResultHandler {
923
+ /// The serialization requirement that the value passed to `onReturn` is required to conform to.
806
924
associatedtype SerializationRequirement
925
+
926
+ // /// Ad-hoc protocol requirement
927
+ // ///
928
+ // /// Invoked when the distributed target execution returns successfully.
929
+ // /// The `value` is the return value of the executed distributed invocation target.
807
930
// func onReturn<Success: SerializationRequirement>(value: Success) async throws
808
931
809
- /// Invoked when the distributed target invocation of a `Void` returning
932
+ /// Invoked when the distributed target execution of a `Void` returning
810
933
/// function has completed successfully.
811
934
func onReturnVoid( ) async throws
812
935
936
+ /// Invoked when the distributed target execution of a target has thrown an error.
937
+ ///
938
+ /// It is not guaranteed that the error conform to the ``SerializationRequirement``;
939
+ /// This guarantee is only given to return values (and offered by `onReturn`).
813
940
func onThrow< Err: Error > ( error: Err ) async throws
814
941
}
815
942
0 commit comments