sails-hook-sourced

A sails.js hook based on sourced tiny framework to provide an event sourcing pattern on top of Waterline

Usage no npm install needed!

<script type="module">
  import sailsHookSourced from 'https://cdn.skypack.dev/sails-hook-sourced';
</script>

README

sails-hook-sourced

sourced hook for Sails v0.10

Status

Stability: 1 - Experimental

Purpose

A sails.js hook based on Matt Walters modules sourced and sourced-repo-mongo to provide to Sails an event sourcing style repository on top of waterline CRUD interface for caching, storing events and snapshots.

Sample setup

npm install sails-hook-sourced

mkdir -p api/hooks/sourced
echo "module.exports = require('sails-hook-sourced');" > api/hooks/sourced/index.js

mkdir -p api/entities
touch api/entities/MyDataEntity.js
touch api/models/MyDataEvents.js
touch api/models/MyDataSnapshots.js
api/entities/MyDataEntity.js
module.exports = {

  options: {
    indices: [],
    models: {
      events: 'MyDataEvents',
      snapshots: 'MyDataSnapshots'
    },
    attributes: ['bar']
  },

  initialize: function(id, cb) {
    this.id = id;
    if (cb) cb();
  },

  myEvent: function(payload, cb) {

    if( payload.foo ) {
      this.bar = payload.foo;
    }

    this.digest('myEvent', payload);

    this.enqueue('myEvent.happened', {
      some: 'additional data',
      foo: this.bar,
      data: payload
      });

    if (cb) cb();
  }

};
api/models/MyDataEvents.js
module.exports = {

  schema: true,

  autoUpdatedAt: false,
  autoCreatedAt: false,

  attributes: {
    entityId: {
      type: 'uuidv4',
      required: true,
      index: true
    },
    method: {
      type: 'string',
      required: true
    },
    data: {
      type: 'json',
      required: true
    },
    timestamp: {
      type: 'integer',
      required: true
    },
    version: {
      type: 'integer',
      required: true
    }
  }
};
api/models/MyDataSnapshots.js
module.exports = {

  schema: false,

  autoCreatedAt: false,
  autoUpdatedAt: false,

  attributes: {
    entityId: {
      type: 'uuidv4',
      required: true,
      index: true
    },
    timestamp: {
      type: 'integer',
      required: true
    },
    snapshotVersion: {
      type: 'integer',
      required: true,
      index: true
    }
  }
};
Sample code
// once sails is lifted
// play `payload` on `myEvent` then commit
MyData.get(payload.id, function(err, myData) {

  if (err) {
    sails.log.error(err);
    return reject(err);
  }

  myData.on('myEvent.happened', function(data) {
    // publish or denormalize data
  });

  myData.myEvent(payload, function(err) {

    if (err) {
      sails.log.error(err);
      return reject(err);
    }

    MyData.commit(myData, function(err) {

      if (err) {
        sails.log.error(err);
        return reject(err);
      }

      resolve();
    });
  });

});

Related talk on sourced module with a DDD / CQRS app

(Youtube) Eventually Consistent Distributed Systems with Node.js for Finance

What is this?

This repo contains a hook, one of the building blocks Sails is made out of.

License

MIT