eventric
Version:
behavior-first application development
131 lines (95 loc) • 4.23 kB
text/coffeescript
uuidGenerator = require 'eventric/uuid_generator'
class ProjectionService
constructor: () ->
= require('eventric').getLogger()
= {}
= {}
initializeInstance: (projectionInstance, params) ->
if ._di
for diName, diFn of ._di
projectionInstance[diName] = diFn
projectionId = uuidGenerator.generateUuid()
aggregateId = null
projectionInstance.$subscribeHandlersWithAggregateId = (_aggregateId) ->
if not _aggregateId
throw new Error 'Missing aggregate id'
aggregateId = _aggregateId
eventNames = null
projectionInstance, params
.then =>
projectionInstance
.then (_eventNames) =>
eventNames = _eventNames
projectionInstance, eventNames, aggregateId
.then =>
projectionId, projectionInstance, eventNames, aggregateId
.then =>
[projectionId] = projectionInstance
.then ->
projectionInstance.isInitialized = true
.then ->
projectionId
_callInitializeOnProjection: (projection, params) ->
new Promise (resolve) ->
if not projection.initialize
return resolve projection
projection.initialize params, ->
resolve projection
_parseEventNamesFromProjection: (projection) ->
new Promise (resolve) ->
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: (projection, eventNames, aggregateId) ->
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
return applyDomainEventsToProjectionPromise
_subscribeProjectionToDomainEvents: (projectionId, projection, eventNames, aggregateId) ->
domainEventHandler = (domainEvent) =>
domainEvent, projection
[projectionId] = []
subscribeProjectionToDomainEventsPromise = Promise.resolve()
eventNames.forEach (eventName) =>
subscribeProjectionToDomainEventsPromise = subscribeProjectionToDomainEventsPromise
.then =>
if aggregateId
.subscribeToDomainEventWithAggregateId eventName, aggregateId, domainEventHandler
else
.subscribeToDomainEvent eventName, domainEventHandler
.then (subscriberId) =>
[projectionId].push subscriberId
return subscribeProjectionToDomainEventsPromise
_applyDomainEventToProjection: (domainEvent, projection) ->
Promise.resolve()
.then =>
if !projection["handle#{domainEvent.name}"]
.warn "ProjectionService: handle#{domainEvent.name} not defined"
return projection["handle#{domainEvent.name}"] domainEvent
getInstance: (projectionId) ->
[projectionId]
destroyInstance: (projectionId) ->
if not projectionId
return Promise.reject new Error 'Missing projection id'
if not [projectionId]
return Promise.reject new Error "Projection with id \"#{projectionId}\" is not initialized"
unsubscribePromises = []
for subscriberId in [projectionId]
unsubscribePromises.push .unsubscribeFromDomainEvent subscriberId
delete [projectionId]
delete [projectionId]
Promise.all unsubscribePromises
module.exports = ProjectionService