Git Product home page Git Product logo

event-machine-skeleton's Introduction

event-machine-skeleton

Dockerized skeleton for prooph software Event Machine

Installation

$ composer create-project proophsoftware/event-machine-skeleton
$ docker run --rm -it -v $(pwd):/app prooph/composer:7.1 install
$ docker-compose up -d
$ docker-compose run php php scripts/create_event_stream.php

Quick Start

Head over to http://localhost:8080 to check if the containers are up and running. You should see a "It works" message.

Let's register a user in our new application. It is a small example that already illustrates the power of Event Machine.

  1. Create a folder named "Model" in src
  2. Add a class UserDescription and copy and paste the content from that gist into it.
  3. Register UserDescription in Event Machine by adding it to config/autoload/global.php (see gist )
  4. Open Postman and import the example collection
  5. Send the "App.RegisterUser" request
  6. Event Machine should return a 202 Accepted response with an empty body
  7. Have a look at the postgres db, see docker-compose.yml of the skeleton for login credentials
  8. The table starting with _ followed by a sha1 hash is your "event_stream" table. You should see a new App.UserWasRegistered event in it.
  9. Test also the "App.ChangeUsername" request
  10. Exercise: Implement the "App.ChangeEmail" use case

Batteries Included

You know the headline from Docker, right? The Event Machine skeleton follows the same principle. It ships with a default set up so that you can start without messing around with configuration and such. The default set up is likely not what you want to use in production. The skeleton can be and should be adapted.

Focus of the skeleton is to provide an easy to use development environment, hence it uses default settings of Postgres, MongoDB and RabbitMQ containers. Make sure to secure the containers before you deploy them anywhere! You should build and use your own docker containers in production anyway. And if you cannot or don't want to use Docker then provide the needed infrastructure the way you prefer and just point event machine to it by adjusting configuration.

Postgres Event Store

Event Machine skeleton uses prooph's Postgres event store by default. It is fully set up with transaction management and event publishing after transaction commit (done by Event Machine).

MongoDB Projections

Event Machine ships with a neat feature called aggregate projection. To explain it we should take a look at the user aggregate description from the linked gist.

$eventMachine
//...
->apply(function (Message $userWasRegistered) {
    $userState = $userWasRegistered->payload();
    return $userState;
});

$eventMachine
//...
->apply(function(array $userState, Message $usernameWasChanged) {
    $userState['username'] = $usernameWasChanged->payload()['newUsername'];
    return $userState;
});

What you return as state from an aggregate apply method is persisted by the aggregate_projection as a document. Each time state changes, the corresponding projection document is updated, too. This happens fully automatic and runs in the background. It is recommended to run each prooph event store projection as a separate background process. Event Machine skeleton gives you an idea how such a projection can look like. Checkout the docker-compose.yml and bin/aggregate_projection.php for details.

If you've followed the quick start you can connect to the MongoDB container (f.e. with mongoDB PHPStorm plugin and default connection settings) and should find a database called event_machine with a collection aggregate_user and a document that has the user id as document _id and all properties set.

The projection uses the aggregate type (in the example it is User), normalizes the type and prefixes it with aggregate_.

The aggregate identifier (int the example it is userId) is used as document id.

The aggregate state is turned into the document itself. Event Machine does not force the type of the state. In the example an array is used but an object would also be possible. See the example shipped with Event Machine for an alternative approach (If you prefer value objects use them!).

Make sure that the MongoDB driver is able to persist the state

Note: You can of course deactivate the projection, if you don't like it or need different behaviour. Remember batteries are included. And of course you can add your own projections and use another database than MongoDB as storage system.

RabbitMQ messaging and web sockets

Event machine ships with a preconfigured rabbitmq docker container using the dev image prooph/rabbitmq. A Humus\AmqpMessageProducer is ready to use (for development) to forward messages via websocket to a JavaScript consumer. An example consumer is shown in public/ws.html.

To test the rabbitmq + websocket set up you can open http://localhost:8080/ws.html in a browser and use the browser debug console to check if a connection to the websocket endpoint under wss://localhost:15691/ws can be established. If you see the stomp client pinging the websocket endpoint everything is fine and you can send some messages from event machine to the client.

A use case is prepared. Send the Àpp.ChangeUsername request again. If you get a 202 response in postman check the browser console and you should find a UsernameWasChanged event. How cool is that?

You could now combine that with your favorite JavaScript framework and directly react on event machine events in the client.

Note: Events are not forwarded to the client automatically. In the UserDescription you can find an example how forwarding is set up per event.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.