Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tech(entity): Introduce metadata system #72

Merged
merged 9 commits into from
Sep 26, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update child and parent using Metadata 🎉
  • Loading branch information
pjechris committed Aug 27, 2024
commit f21cdd7c16fb4de5e7aa77a3d34a02de283737d9
16 changes: 16 additions & 0 deletions Sources/CohesionKit/EntityStore.swift
Original file line number Diff line number Diff line change
@@ -180,6 +180,14 @@ public class EntityStore {
return node
}

for (childRef, _) in node.metadata.childrenRefs {
guard let childNode = storage[childRef]?.unwrap() as? AnyEntityNode else {
continue
}

childNode.removeParent(node)
}

// clear all children to avoid a removed child to be kept as child
node.removeAllChildren()

@@ -197,6 +205,14 @@ public class EntityStore {
logger?.didFailedToStore(T.self, id: entity.id, error: error)
}

for parentRef in node.metadata.parentsRefs {
guard let parentNode = storage[parentRef]?.unwrap() as? AnyEntityNode else {
continue
}

parentNode.updateEntityRelationship(node)
}

return node
}

5 changes: 5 additions & 0 deletions Sources/CohesionKit/Storage/EntitiesStorage.swift
Original file line number Diff line number Diff line change
@@ -19,6 +19,11 @@ struct EntitiesStorage {
set { indexes[key(for: T.self, id: id)] = Weak(value: newValue) }
}

subscript(_ key: String) -> AnyWeak? {
get { indexes[key] }
set { indexes[key] = newValue }
}

private func key<T>(for type: T.Type, id: Any) -> String {
"\(type)-\(id)"
}
31 changes: 27 additions & 4 deletions Sources/CohesionKit/Storage/EntityNode.swift
Original file line number Diff line number Diff line change
@@ -3,12 +3,12 @@ import Combine

struct EntityMetadata {
/// children this entity is referencing/using
/// key: the children keypath in the parent, value: the key in EntitieStorage
// TODO: change value to a ObjectKey
var childrenRefs: [AnyKeyPath: String] = [:]
// TODO: change key to a ObjectKey
var childrenRefs: [String: AnyKeyPath] = [:]

/// parents referencing this entity. This means this entity should be listed inside its parents `EntityMetadata.childrenRefs` attribute
var parentsRefs: Set<ObjectKey> = []
// TODO: Change value to ObjectKey
var parentsRefs: Set<String> = []
/// alias referencing this entity
var aliasesRefs: Set<String> = []

@@ -24,8 +24,11 @@ struct EntityMetadata {
protocol AnyEntityNode: AnyObject {
var value: Any { get }
var metadata: EntityMetadata { get }
var storageKey: String { get }

func nullify()
func removeParent(_ node: AnyEntityNode)
func updateEntityRelationship<T>(_ node: EntityNode<T>)
}

/// A graph node representing a entity of type `T` and its children. Anytime one of its children is updated the node
@@ -93,10 +96,30 @@ class EntityNode<T>: AnyEntityNode {

func removeAllChildren() {
children = [:]
metadata.childrenRefs = [:]
}

func removeParent(_ node: AnyEntityNode) {
metadata.parentsRefs.remove(node.storageKey)
}

func updateEntityRelationship<U>(_ node: EntityNode<U>) {
guard let keyPath = metadata.childrenRefs[node.storageKey] else {
return
}

guard let writableKeyPath = keyPath as? WritableKeyPath<T, U> else {
return
}

ref.value[keyPath: writableKeyPath] = node.ref.value
}

/// observe one of the node child
func observeChild<C>(_ childNode: EntityNode<C>, for keyPath: WritableKeyPath<T, C>) {
metadata.childrenRefs[childNode.storageKey] = keyPath
childNode.metadata.parentsRefs.insert(storageKey)

observeChild(childNode, identity: keyPath) { root, newValue in
root[keyPath: keyPath] = newValue
}
2 changes: 1 addition & 1 deletion Tests/CohesionKitTests/Storage/EntityNodeTests.swift
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ class EntityNodeTests: XCTestCase {
observerCalled = true
}

node = EntityNode(ref: entityRef, modifiedAt: startTimestamp)
node = EntityNode(ref: entityRef, key: "RootFixture-1", modifiedAt: startTimestamp)
node.observeChild(childNode, for: \.singleNode)

try childNode.updateEntity(newChild, modifiedAt: nil)