@@ -18,7 +18,8 @@ import _Distributed
18
18
19
19
public struct ActorAddress : Hashable , Sendable , Codable {
20
20
public let address : String
21
- public init ( parse address : String ) {
21
+
22
+ public init ( parse address: String ) {
22
23
self . address = address
23
24
}
24
25
@@ -33,7 +34,7 @@ public struct ActorAddress: Hashable, Sendable, Codable {
33
34
}
34
35
}
35
36
36
- // ==== Fake Transport ---------------------------------------------------------
37
+ // ==== Noop Transport ---------------------------------------------------------
37
38
38
39
public struct FakeActorSystem : DistributedActorSystem {
39
40
public typealias ActorID = ActorAddress
@@ -65,7 +66,7 @@ public struct FakeActorSystem: DistributedActorSystem {
65
66
66
67
public func actorReady< Act> ( _ actor : Act )
67
68
where Act: DistributedActor ,
68
- Act. ID == ActorID {
69
+ Act. ID == ActorID {
69
70
}
70
71
71
72
public func resignID( _ id: ActorID ) {
@@ -78,28 +79,27 @@ public struct FakeActorSystem: DistributedActorSystem {
78
79
public func remoteCall< Act, Err, Res> (
79
80
on actor : Act ,
80
81
target: RemoteCallTarget ,
81
- invocationDecoder : inout InvocationDecoder ,
82
+ invocation invocationEncoder : inout InvocationEncoder ,
82
83
throwing: Err . Type ,
83
84
returning: Res . Type
84
85
) async throws -> Res
85
86
where Act: DistributedActor ,
87
+ Act. ID == ActorID ,
86
88
Err: Error ,
87
- // Act.ID == ActorID,
88
89
Res: SerializationRequirement {
89
90
throw ExecuteDistributedTargetError ( message: " Not implemented. " )
90
91
}
91
92
92
93
func remoteCallVoid< Act, Err> (
93
94
on actor : Act ,
94
95
target: RemoteCallTarget ,
95
- invocationDecoder : inout InvocationDecoder ,
96
+ invocation invocationEncoder : inout InvocationEncoder ,
96
97
throwing: Err . Type
97
98
) async throws
98
99
where Act: DistributedActor ,
99
100
Act. ID == ActorID ,
100
101
Err: Error {
101
102
throw ExecuteDistributedTargetError ( message: " Not implemented. " )
102
-
103
103
}
104
104
}
105
105
@@ -126,3 +126,187 @@ public struct FakeInvocation: DistributedTargetInvocationEncoder, DistributedTar
126
126
public typealias SerializationRequirement = Codable
127
127
}
128
128
}
129
+
130
+ // ==== Fake Roundtrip Transport -----------------------------------------------
131
+
132
+ // TODO: not thread safe...
133
+ public final class FakeRoundtripActorSystem : DistributedActorSystem , @unchecked Sendable {
134
+ public typealias ActorID = ActorAddress
135
+ public typealias InvocationEncoder = FakeRoundtripInvocation
136
+ public typealias InvocationDecoder = FakeRoundtripInvocation
137
+ public typealias SerializationRequirement = Codable
138
+
139
+ var activeActors : [ ActorID : any DistributedActor ] = [ : ]
140
+
141
+ public init ( ) { }
142
+
143
+ public func resolve< Act> ( id: ActorID , as actorType: Act . Type )
144
+ throws -> Act ? where Act: DistributedActor {
145
+ print ( " | resolve \( id) as remote // this system always resolves as remote " )
146
+ return nil
147
+ }
148
+
149
+ public func assignID< Act> ( _ actorType: Act . Type ) -> ActorID
150
+ where Act: DistributedActor {
151
+ let id = ActorAddress ( parse: " <unique-id> " )
152
+ print ( " | assign id: \( id) for \( actorType) " )
153
+ return id
154
+ }
155
+
156
+ public func actorReady< Act> ( _ actor : Act )
157
+ where Act: DistributedActor ,
158
+ Act. ID == ActorID {
159
+ print ( " | actor ready: \( actor ) " )
160
+ self . activeActors [ actor . id] = actor
161
+ }
162
+
163
+ public func resignID( _ id: ActorID ) {
164
+ print ( " X resign id: \( id) " )
165
+ }
166
+
167
+ public func makeInvocationEncoder( ) -> FakeRoundtripInvocation {
168
+ . init( )
169
+ }
170
+
171
+ private var remoteCallResult : Any ? = nil
172
+
173
+ public func remoteCall< Act, Err, Res> (
174
+ on actor : Act ,
175
+ target: RemoteCallTarget ,
176
+ invocation: inout InvocationEncoder ,
177
+ throwing errorType: Err . Type ,
178
+ returning returnType: Res . Type
179
+ ) async throws -> Res
180
+ where Act: DistributedActor ,
181
+ Act. ID == ActorID ,
182
+ Err: Error ,
183
+ Res: SerializationRequirement {
184
+ print ( " >> remoteCall: on: \( actor ) ), target: \( target) , invocation: \( invocation) , throwing: \( String ( reflecting: errorType) ) , returning: \( String ( reflecting: returnType) ) " )
185
+ guard let targetActor = activeActors [ actor . id] else {
186
+ fatalError ( " Attempted to call mock 'roundtrip' on: \( actor . id) without active actor " )
187
+ }
188
+
189
+ func doIt< A: DistributedActor > ( active: A ) async throws -> Res {
190
+ guard ( actor . id) == active. id as! ActorID else {
191
+ fatalError ( " Attempted to call mock 'roundtrip' on unknown actor: \( actor . id) , known: \( active. id) " )
192
+ }
193
+
194
+ let resultHandler = FakeRoundtripResultHandler { self . remoteCallResult = $0 }
195
+ try await executeDistributedTarget (
196
+ on: active,
197
+ mangledTargetName: target. mangledName,
198
+ invocationDecoder: & invocation,
199
+ handler: resultHandler
200
+ )
201
+
202
+ print ( " << remoteCall return: \( remoteCallResult!) " )
203
+ return remoteCallResult! as! Res
204
+ }
205
+ return try await _openExistential ( targetActor, do: doIt)
206
+ }
207
+
208
+ public func remoteCallVoid< Act, Err> (
209
+ on actor : Act ,
210
+ target: RemoteCallTarget ,
211
+ invocation: inout InvocationEncoder ,
212
+ throwing: Err . Type
213
+ ) async throws
214
+ where Act: DistributedActor ,
215
+ Act. ID == ActorID ,
216
+ Err: Error {
217
+ print ( " remoteCallVoid: on: \( actor ) , target: \( target) , invocation: \( invocation) , throwing: \( throwing) " )
218
+ return ( )
219
+ }
220
+
221
+ }
222
+
223
+ public struct FakeRoundtripInvocation : DistributedTargetInvocationEncoder , DistributedTargetInvocationDecoder {
224
+ public typealias SerializationRequirement = Codable
225
+
226
+ var genericSubs : [ Any . Type ] = [ ]
227
+ var arguments : [ Any ] = [ ]
228
+ var returnType : Any . Type ? = nil
229
+ var errorType : Any . Type ? = nil
230
+
231
+ public mutating func recordGenericSubstitution< T> ( _ type: T . Type ) throws {
232
+ print ( " > encode generic sub: \( type) " )
233
+ genericSubs. append ( type)
234
+ }
235
+
236
+ public mutating func recordArgument< Argument: SerializationRequirement > ( _ argument: Argument ) throws {
237
+ print ( " > encode argument: \( argument) " )
238
+ arguments. append ( argument)
239
+ }
240
+ public mutating func recordErrorType< E: Error > ( _ type: E . Type ) throws {
241
+ print ( " > encode error type: \( type) " )
242
+ self . errorType = type
243
+ }
244
+ public mutating func recordReturnType< R: SerializationRequirement > ( _ type: R . Type ) throws {
245
+ print ( " > encode return type: \( type) " )
246
+ self . returnType = type
247
+ }
248
+ public mutating func doneRecording( ) throws {
249
+ print ( " > done recording " )
250
+ }
251
+
252
+ // === decoding --------------------------------------------------------------
253
+
254
+ public func decodeGenericSubstitutions( ) throws -> [ Any . Type ] {
255
+ print ( " > decode generic subs: \( genericSubs) " )
256
+ return genericSubs
257
+ }
258
+
259
+ var argumentIndex : Int = 0
260
+ public mutating func decodeNextArgument< Argument> (
261
+ _ argumentType: Argument . Type ,
262
+ into pointer: UnsafeMutablePointer < Argument >
263
+ ) throws {
264
+ guard argumentIndex < arguments. count else {
265
+ fatalError ( " Attempted to decode more arguments than stored! Index: \( argumentIndex) , args: \( arguments) " )
266
+ }
267
+
268
+ let anyArgument = arguments [ argumentIndex]
269
+ guard let argument = anyArgument as? Argument else {
270
+ fatalError ( " Cannot cast argument \( anyArgument) to expected \( Argument . self) " )
271
+ }
272
+
273
+ print ( " > decode argument: \( argument) " )
274
+ pointer. pointee = argument
275
+ argumentIndex += 1
276
+ }
277
+
278
+ public func decodeErrorType( ) throws -> Any . Type ? {
279
+ print ( " > decode return type: \( errorType. map { String ( describing: $0) } ?? " nil " ) " )
280
+ return self . errorType
281
+ }
282
+
283
+ public func decodeReturnType( ) throws -> Any . Type ? {
284
+ print ( " > decode return type: \( returnType. map { String ( describing: $0) } ?? " nil " ) " )
285
+ return self . returnType
286
+ }
287
+ }
288
+
289
+ @available ( SwiftStdlib 5 . 5 , * )
290
+ public struct FakeRoundtripResultHandler : DistributedTargetInvocationResultHandler {
291
+ public typealias SerializationRequirement = Codable
292
+
293
+ let store : ( Any ) -> Void
294
+ init ( _ store: @escaping ( Any ) -> Void ) {
295
+ self . store = store
296
+ }
297
+
298
+ public func onReturn< Res> ( value: Res ) async throws {
299
+ print ( " << onReturn: \( value) " )
300
+ store ( value)
301
+ }
302
+
303
+ public func onThrow< Err: Error > ( error: Err ) async throws {
304
+ print ( " << onThrow: \( error) " )
305
+ store ( error)
306
+ }
307
+ }
308
+
309
+ // ==== Helpers ----------------------------------------------------------------
310
+
311
+ @_silgen_name ( " swift_distributed_actor_is_remote " )
312
+ func __isRemoteActor( _ actor : AnyObject ) -> Bool
0 commit comments