apple / swift-distributed-actors

Peer-to-peer cluster implementation for Swift Distributed Actors
https://apple.github.io/swift-distributed-actors/
Apache License 2.0
580 stars 54 forks source link

DA spawned by a ClusterSingleton inherits _Props and leads to duplicateActorPath error #1131

Closed yim-lee closed 12 months ago

yim-lee commented 1 year ago

I have a cluster singleton (e.g., Singleton) that spawns another distributed actor (e.g., Greeter) to do some work.

distributed actor Singleton: ClusterSingleton {
    typealias ActorSystem = ClusterSystem

    private let greeter: Greeter

    init(actorSystem: ActorSystem) {
        self.actorSystem = actorSystem
        self.greeter = Greeter(actorSystem: actorSystem)
    }
}

distributed actor Greeter {
    typealias ActorSystem = ClusterSystem

    distributed func greet() {
        print("Hello!")
    }
}

I have a test that starts the cluster singleton in a single-node cluster like so:

        let singleton = try await clusterSystem.singleton.host(name: "test-singleton") { actorSystem in
            Singleton(actorSystem: actorSystem)
        }

The test crashes with error:

DistributedCluster/ClusterSystem.swift:759: Fatal error: 'try!' expression unexpectedly raised an error: ClusterSystemError(duplicateActorPath(path: /user/test-singleton), at: DistributedCluster/Refs.swift:642)

Upon inspecting trace logs I see that Greeter has inherited the _Props of Singleton, which results in the two actors having the same id:

2023-07-08T11:31:13-0700 trace test : actor/id=[$wellKnown: test-singleton] actor/type=Singleton cluster/node=sact://test@127.0.0.1:9001 [DistributedCluster] Assign identity
2023-07-08T11:31:13-0700 trace test : actor/id=[$wellKnown: test-singleton] actor/type=Greeter cluster/node=sact://test@127.0.0.1:9001 [DistributedCluster] Assign identity
2023-07-08T11:31:13-0700 trace test : actor/id=[$wellKnown: test-singleton] actor/type=Greeter cluster/node=sact://test@127.0.0.1:9001 [DistributedCluster] Actor ready
2023-07-08T11:31:13-0700 trace test : actor/id=[$wellKnown: test-singleton] actor/type=Singleton cluster/node=sact://test@127.0.0.1:9001 [DistributedCluster] Actor ready

The error does NOT occur if Greeter is initialized inside a distributed func invoked outside:

distributed actor Singleton: ClusterSingleton {
    typealias ActorSystem = ClusterSystem

    private var greeter: Greeter?

    init(actorSystem: ActorSystem) {
        self.actorSystem = actorSystem
    }

    distributed func initGreeter() {
        self.greeter = Greeter(actorSystem: actorSystem)
    }
}

let singleton = try await clusterSystem.singleton.host(name: "test-singleton") { actorSystem in
    Singleton(actorSystem: actorSystem)
}
try await singleton.initGreeter()
ktoso commented 1 year ago

Thanks, something silly going on here with our move away from paths -- I'll investigate

ktoso commented 1 year ago

rdar://112434926