Skip to content

Instantly share code, notes, and snippets.

@andrejewski
Created July 19, 2018 02:01
Show Gist options
  • Save andrejewski/8724b2022368e09fd67cc79686f88fb4 to your computer and use it in GitHub Desktop.
Save andrejewski/8724b2022368e09fd67cc79686f88fb4 to your computer and use it in GitHub Desktop.
A data reconciler with subscriptions
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