apple / apple/swift-distributed-actors
Follow up: Receptionist removeSingleRegistrationNodeRelation real impl
- Dominant language
- Swift
- Stars
- 679
- Forks
- 84
- PR merge metrics
- No merged PRs in 30d
Description
Implement this:
```
private func removeSingleRegistrationNodeRelation(key: AnyRegistrationKey, node: UniqueNode?) {
// FIXME: Implement me (!), we need to make the storage a counter
// and decrement here by one; once the counter reaches zero we know there is no more relationship
// and we can prune this key/node relationship
}
```
context:
- when we store registrations we also need a reverse lookup to avoid scanning "all" registrations when a node dies
- when we register, we associate `node -> Set`
- when an actor dies, we cannot just remove this, since there may be a few actors under the same key under the node
- so we need to change `Set` to some `Registration`, and we should decrement this counter in `removeSingleRegistrationNodeRelation`
- when it reaches zero, we can remove that key
Those keys are used when we see a receptionist (or node) die, and then we take this node's keys, and scan those key's actors "which ones were on that node which is now dead" and we remove them. This mapping is in order to avoid scanning all keys and all actors - we only scan keys we know that node has had actually
```swift
internal var _registrations: [AnyRegistrationKey: Set] = [:]
private var _subscriptions: [AnyRegistrationKey: Set] = [:]
/// Per (receptionist) node mapping of which keys are presently known to this receptionist on the given node.
/// This is used to perform quicker cleanups upon a node/receptionist crashing, and thus all existing references
/// on that node should be removed from our storage.
private var _registeredKeysByNode: [UniqueNode: Set] = [:]
/// Allows for reverse lookups, when an actor terminates, we know from which registrations and subscriptions to remove it from.
internal var _addressToKeys: [ActorAddress: Set] = [:]
// ==== --------------------------------------------------------------------------------------------------------
// MARK: Registrations
/// - returns: `true` if the value was a newly inserted value, `false` otherwise
func addRegistration(key: AnyRegistrationKey, ref: AddressableActorRef) -> Bool {
self.addRefKeyMapping(address: ref.address, key: key)
self.storeRegistrationNodeRelation(key: key, node: ref.address.node)
return self.addTo(dict: &self._registrations, key: key, value: ref)
}
func removeRegistration(key: AnyRegistrationKey, ref: AddressableActorRef) -> Set? {
_ = self.removeFromKeyMappings(ref)
self.removeSingleRegistrationNodeRelation(key: key, node: ref.address.node)
return self.removeFrom(dict: &self._registrations, key: key, value: ref)
}
func registrations(forKey key: AnyRegistrationKey) -> Set? {
self._registrations[key]
}
private func storeRegistrationNodeRelation(key: AnyRegistrationKey, node: UniqueNode?) {
if let node = node {
self._registeredKeysByNode[node, default: []].insert(key)
}
}
```
Contributor guide
Research direction
Start with removeSingleRegistrationNodeRelation, storeRegistrationNodeRelation, removeRegistration, and the _registeredKeysByNode mapping. Trace how repeated registrations on one node are recorded and removed; done means the relation remains while its count is nonzero and the key is pruned when the count reaches zero.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- distributed-systems
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100