I've just realised, that this could be a Swift runtime issue.
This is very specific, but still a bit surprising.
When using a protocol with associated type, which will be used then as a generic (see reproducible for example)—cluster will crash with error:
Thread 1: Fatal error: Error raised at top level: DistributedCluster.GenericRemoteCallError(message: "Remote call error of [ExecuteDistributedTargetError] type occurred")
Reproduction
you need ClusterSystem package (swift-distributed-actors)
import Distributed
import DistributedCluster
typealias DefaultDistributedActorSystem = ClusterSystem
protocol SomeProtocol: Codable {
associatedtype Message: Codable
}
struct Implementation: SomeProtocol {
typealias Message = String
}
distributed actor WorkerActor {
static var key: DistributedReception.Key<WorkerActor> { "worker_actor" }
distributed func getSome<S: SomeProtocol>(_ protocol: S, message: S.Message) -> String {
"help"
}
init(actorSystem: ClusterSystem) async {
self.actorSystem = actorSystem
await self.actorSystem.receptionist.checkIn(self, with: WorkerActor.key)
}
}
distributed actor ReceptionistActor {
var actors: [WorkerActor] = []
func listen() {
Task {
for await actor in await actorSystem.receptionist.listing(of: WorkerActor.key) {
self.actors.append(actor)
}
}
}
distributed func getLatest() -> WorkerActor? {
self.actors.last
}
init(actorSystem: ActorSystem) async {
self.actorSystem = actorSystem
self.listen()
}
}
let receptionist = await ClusterSystem("receptionist")
let someActorsNode = await ClusterSystem("spme_actors") { settings in
settings.bindPort = 1111
}
receptionist.cluster.join(endpoint: someActorsNode.settings.endpoint)
try await receptionist.cluster.joined(node: someActorsNode.cluster.node, within: .seconds(10))
let receptionistActor = await ReceptionistActor(actorSystem: receptionist)
let worker = await WorkerActor(actorSystem: someActorsNode)
// local actor works
try await print(worker.getSome(impl, message: "hello"))
// wait a bit for receptionist
try await Task.sleep(for: .seconds(3))
let remoteActor = try await receptionistActor.getLatest()
let impl = Implementation()
// Remote actor will crash
try await print(remoteActor?.getSome(impl, message: "hello") ?? "")
print("done")
Description
Basically this is a copy of an issue in swift-distributed-actors repo: https://github.com/apple/swift-distributed-actors/issues/1156
I've just realised, that this could be a Swift runtime issue.
This is very specific, but still a bit surprising. When using a protocol with associated type, which will be used then as a generic (see reproducible for example)—cluster will crash with error:
Reproduction
you need ClusterSystem package (swift-distributed-actors)
Stack dump
Expected behavior
Remote actor call should behave the same as when local with associated types in protocol.
Environment
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) Target: arm64-apple-macosx14.0
Additional information
Note—everything will start working again if you'll change associated type to separate protocol, like:
and update function accordingly: