apple / apple/swift-distributed-actors

Follow up: Receptionist removeSingleRegistrationNodeRelation real impl

Open
#520 0 comments 0 reactions 0 assignees View on GitHub
1 - triaged help wanted t:receptionist
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.