Created
July 19, 2018 02:01
-
-
Save andrejewski/8724b2022368e09fd67cc79686f88fb4 to your computer and use it in GitHub Desktop.
A data reconciler with subscriptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function createReconciler ({ | |
mergeEntity, | |
getEntityKey, | |
entityStore = {}, | |
subscriptions = new Set(), | |
}) { | |
function notify (subscriptions) { | |
subscriptions.forEach(subscription => { | |
const entities = [] | |
subscription.entities.forEach(key => { | |
entities.push(entityStore[key]) | |
}) | |
subscription.callback(entities) | |
}) | |
} | |
return { | |
ingest (entities) { | |
const effectedSubscriptions = new Set() | |
entities.forEach(entity => { | |
const key = getEntityKey(entity) | |
const existingEntity = entityStore[key] | |
const updatedEntity = mergeEntity(existingEntity, entity) | |
let activeSubscriptions = entityDependentStore[entityKey] | |
if (!activeSubscriptions) { | |
activeSubscriptions = entityDependentStore[entityKey] = new Set() | |
} | |
subscriptions.forEach(subscription => { | |
const startSize = activeSubscriptions.size | |
if (subscription.predicate(entity)) { | |
activeSubscriptions.add(subscription) | |
subscription.entities.add(entityKey) | |
} else { | |
activeSubscriptions.delete(subscription) | |
subscription.entities.delete(entityKey) | |
} | |
if (startSize !== activeSubscriptions.size) { | |
effectedSubscriptions.add(subscription) | |
} | |
}) | |
if (!activeSubscriptions.size) { | |
delete entityDependentStore[entityKey] | |
} | |
entityStore[key] = updatedEntity | |
}) | |
notify(effectedSubscriptions) | |
}, | |
redact (entities) { | |
const effectedSubscriptions = new Set() | |
entities.forEach(entity => { | |
const key = getEntityKey(entity) | |
const dependentSubscriptions = entityDependentStore[key] | |
if (dependentSubscriptions) { | |
dependentSubscriptions.forEach(subscription => { | |
effectedSubscriptions.add(subscription) | |
subscription.entities.delete(key) | |
}) | |
} | |
delete entityStore[key] | |
}) | |
notify(effectedSubscriptions) | |
}, | |
subscribe (subscription) { | |
const { predicate } = subscription | |
const entities = new Set() | |
for (const key in entityStore) { | |
if (predicate(entityStore[key])) { | |
entities.add(key) | |
} | |
} | |
subscription.entities = entities | |
subscriptions.add(subscription) | |
notify([subscription]) | |
return () => { | |
subscriptions.delete(subscription) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment