eventric
Version:
behavior-first application development
144 lines (106 loc) • 4.87 kB
text/coffeescript
logger = require 'eventric/logger'
uidGenerator = require 'eventric/uid_generator'
class Projection
constructor: () ->
= {}
= {}
= {}
initializeInstance: (projectionName, Projection, params) ->
if typeof Projection is 'function'
projection = new Projection
else
projection = Projection
if ._di
for diName, diFn of ._di
projection[diName] = diFn
projectionId = uidGenerator.generateUid()
aggregateId = null
projection.$subscribeHandlersWithAggregateId = (_aggregateId) ->
aggregateId = _aggregateId
eventNames = null
projectionName, projection, params
.then =>
projection
.then (_eventNames) =>
eventNames = _eventNames
projectionId, projection, eventNames, aggregateId
.then =>
projectionId, projectionName, projection, eventNames, aggregateId
.then =>
[projectionId] = projection
.then ->
projection.isInitialized = true
.then ->
projectionId
_callInitializeOnProjection: (projectionName, projection, params) ->
new Promise (resolve, reject) =>
if not projection.initialize
logger.debug "[#{@_context.name}] No initialize function on Projection #{projectionName} given, skipping"
return resolve projection
logger.debug "[#{@_context.name}] Calling initialize on Projection #{projectionName}"
projection.initialize params, =>
logger.debug "[#{@_context.name}] Finished initialize call on Projection #{projectionName}"
resolve projection
_parseEventNamesFromProjection: (projection) ->
new Promise (resolve, reject) ->
eventNames = []
for key, value of projection
if (key.indexOf 'handle') is 0 and (typeof value is 'function')
eventName = key.replace /^handle/, ''
eventNames.push eventName
resolve eventNames
_applyDomainEventsFromStoreToProjection: (projectionId, projection, eventNames, aggregateId) ->
[projectionId] = {}
if aggregateId
findEvents = .findDomainEventsByNameAndAggregateId eventNames, aggregateId
else
findEvents = .findDomainEventsByName eventNames
findEvents
.then (domainEvents) =>
if not domainEvents or domainEvents.length is 0
return
applyDomainEventsToProjectionPromise = Promise.resolve()
domainEvents.forEach (domainEvent) =>
applyDomainEventsToProjectionPromise = applyDomainEventsToProjectionPromise.then =>
domainEvent, projection
.then =>
[projectionId][domainEvent.id] = true
return applyDomainEventsToProjectionPromise
_subscribeProjectionToDomainEvents: (projectionId, projectionName, projection, eventNames, aggregateId) ->
domainEventHandler = (domainEvent) =>
if [projectionId][domainEvent.id]
return
domainEvent, projection
.then =>
[projectionId][domainEvent.id] = true
return
subscribeProjectionToDomainEventsPromise = Promise.resolve()
eventNames.forEach (eventName) =>
subscribeProjectionToDomainEventsPromise = subscribeProjectionToDomainEventsPromise.then =>
if aggregateId
.subscribeToDomainEventWithAggregateId eventName, aggregateId, domainEventHandler
else
.subscribeToDomainEvent eventName, domainEventHandler
.then (subscriberId) =>
[projectionId] ?= []
[projectionId].push subscriberId
return subscribeProjectionToDomainEventsPromise
_applyDomainEventToProjection: (domainEvent, projection) =>
Promise.resolve()
.then =>
if !projection["handle#{domainEvent.name}"]
logger.debug "Tried to apply DomainEvent '#{domainEvent.name}' to Projection without a matching handle method"
return
return projection["handle#{domainEvent.name}"] domainEvent
getInstance: (projectionId) ->
[projectionId]
destroyInstance: (projectionId) ->
if not [projectionId]
return Promise.reject new Error 'Missing attribute projectionId'
unsubscribePromises = []
for subscriberId in [projectionId]
unsubscribePromises.push .unsubscribeFromDomainEvent subscriberId
delete [projectionId]
delete [projectionId]
Promise.all unsubscribePromises
module.exports = Projection