Skip to content

Instantly share code, notes, and snippets.

@otaviosoares
Created July 13, 2016 19:40
Show Gist options
  • Save otaviosoares/f31b067fd5ca017cb8c61eeec1dadd42 to your computer and use it in GitHub Desktop.
Save otaviosoares/f31b067fd5ca017cb8c61eeec1dadd42 to your computer and use it in GitHub Desktop.
seneca-cqrs-example.js
'use strict'
var seneca = require('seneca')
function eventStore () {
// This is the acid part, if this stores correctly all events are
// emitted, if not you die because you are in an invalid state. this
// whole part is usually based on optimistic concurrency.
seneca.add('role:eventStore,cmd:update', functiom (msg, done) {
// Assuming our save went well for each event, we publish them
// for readmodels or anyone else to listen to.
msg.events.forEach((event) => {
seneca.act(event, {fatal$: false})
})
})
}
function productHandler () {
// In seneca these parts are your agreggates.
senea.add('role:product,cmd:create', function (msg, done) {
// create product would create the events needed based on
// the message provided and may create multiple messages.
createProduct(msg, (events) => {
// forward all events on to the store, we don't need a response.
this.act('role:eventStore,cmd:update', {events: events})
done()
})
})
}
function productReadModel () {
// We want all events related to product.
seneca.add('role:product,event:*', function (msg, done) {
// add products to some run time cache
done()
})
// Give people the data we have, it will be eventually consistent.
seneca.add('role:product,query:listAll', function (msg, done) {
done(null, {data: {...}})
})
}
// Send a command once per second, commands are fire and forget.
setTimeout(() => {
seneca.act('role:product,cmd:create', {name: 'apple'})
}, 1000)
// Query a read-model, these are populated via the event stream
setTimeout(() => {
seneca.act('role:product,query:listAll', (err, reply) => {
console.log(err || reply.data)
})
}, 1200)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment