gorewind

command module
v0.0.0-...-301ae46 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2015 License: AGPL-3.0 Imports: 8 Imported by: 0

README

============
Rewind in Go
============
.. image:: https://secure.travis-ci.org/JensRantil/gorewind.png?branch=develop
   :target: http://travis-ci.org/#!/JensRantil/gorewind

This is the next generation of `Rewind`_. The intention is to bring higher
concurrency and support for multiple streams. Initially only a single
storage backend will be supported (LevelDB).

.. _Rewind: https://github.com/JensRantil/rewind

The implementation is written in the Go programming language.

Currently, this project is highly experimental and alpha.

Other things:

* Tests are executed using `make test`.

* I'll try to stick to http://www.semver.org when it comes to versioning.

Background
==========

Have you ever been nervous of all those DBMSs schema changes when you
are deploying your applications? They are gonna take too long, or break
backward compatibility? Have you ever thought "Crap, I wish I had stored
that information since earlier"? Have you ever felt your writing
patterns and your reading patterns differ a lot, making things harder to
scale? Issues like these can be solved using *CQRS* and *event
sourcing*.

*CQRS* (Command-Query Response Segregation) is an architectural pattern
that aims to solve these issues by splitting up your architectural
system into two parts:

* A *write side* that takes care of validating input and optimizes for
  fast writes. The write side takes commands and outputs corresponding
  events if the command validates correctly.

* A *read side* that listens to incoming events from the write side. The
  read side is optimized for fast reads and incrementally build up state
  that can be queried fast.

While not required, it is common to use messaging between the write and
read sides. This means that the system will be in an inconsistent state
from time to time. This is usually not an issue and can be overcome in
various ways.

A common pattern used together with CQRS is *event sourcing*. The
concept can be summarized as using state changes as primary persistence,
instead of the final state. The state changes are called *events* and
they are generated by the write side and delivered to the read side.

The events are persisted in an event store that sits inbetween the read
and write side of things. It takes care of three things:

* persisting all events to disk.

* being a hub/broker replicating all events from the write to the read
  side of things.

* allowind fast querying of events so that different parts of the system
  can be synced back on track and new components can be brought back in
  play.

*Gorewind* is an event store application that talks ZeroMQ and is
written in Go. It is also a library that can be used to embed event
store functionality into a Go application.

Installing/Developing
=====================

There are currently no releases of Gorewind. However, if you would like to
build Gorewind from code you need to do the following:

1. Install Go 1.0 or 1.1.

2. Make sure `libzmq`/`libzmq3` (ZeroMQ) version 3 is installed on the system
   together with its development files. It has been tested to work with
   version 3.2.

3. Ser up a `GOPATH` environment variable. You can read more about it here:
   http://golang.org/doc/code.html

3. In terminal::

    $ git clone https://github.com/JensRantil/gorewind.git
    $ go get -tags zmq_3_x github.com/alecthomas/gozmq
    $ go get
    ...
    $ make test
    ... (make sure tests are not failing)
    $ make build

...and voilá, `gorewind` binary should have been created.

Concepts
========

Gorewind stores ordered *events* in independent *event streams* (usually
only referred to as *streams* in code and documentation). Each event has
a unique identifier (within its stream) and some data.

The *identifier* for an event is used by clients to be able to query
events. The identifier is a variable length byte array and should
be treated as such by the client.

The event *data* is treated as a variable length series of bytes by
Gorewind server. Therefor, the server has no concept of whether the
event is JSON, XML, protobuf, whatever. Gorewind does also not store any
meta data about each event, such as creation date, origin, author etc.
Both serialization format and meta data should be dealt with by the
event store clients.

Talking to `gorewind`
=====================

The Gorewind server has two different wire protocols. Each is using
ZeroMQ as low level transport protocol. Each wire protocol has one
single ZeroMQ endpoint in Gorewind:

* **A streaming response (ROUTER) socket** which is used for receiving
  new events and querying chronological slices of all events throughout
  time. The connecting ZeroMQ socket must be of type DEALER. The reason
  for not using a plain REQ/REP constellation is because they would not
  handle streaming of bigger results. See the "Advanced Request-Reply
  Patterns" in the ZeroMQ Guide for more information.

* **A streaming (PUB) socket** which publishes submitted events that has
  been persisted. The published events can be filtered based on the
  stream.is used by all clients that are interested in all new incoming
  events.

Each endpoint is configurable through command line when starting
``gorewind``. Issue ``gorewind --help`` to get a list of the specific
command line arguments ``gorewind`` can handle.

*Note that the wire protocol is still under heavy development. Pull
requests and improvement proposals are welcome!*

Dealer/response socket
-----------------------

The socket for querying Gorewind is the one which has the most advanced
wire protocol. The socket is of type ROUTER, which makes is possible for
Gorewind to handle incoming requests concurrently. Since the client
socket is a DEALER, the server can return arbitrarily many reply
messages for each request. A typical converation between a client (C)
and Gorewind (R) looks like this::

    C: Request
    R: Response
    ... (1 to N responses)
    R: Response
    C: Request
    R: Response
    ...

Request types
`````````````
Each request is a multipart message. The first part is a string that
specifies the type of request. There are multiple request types:

PUBLISH
'''''''
Used for publishing an event. Apart from the command header, it consists of two frames:

1. *Stream identifier* used to specify which stream the event should be
   added to. Treated simply as a byte array, but it's recommended to
   keep it an ASCII string to for facilitate easier debugging.

2. *Event data* that describes the event that happened. Gorewind does not
   know anything about the serialization format. It always simply stores
   the bytes. However, it is recommended to keep the format simple (such
   as JSON) to facilitate debugging.

Each new incoming/published event triggers that it is to be streamed out
to all listening clients.

On successful reception of an event, Gorewind responds with a 2-framed
message where:

* the first message frame contains the ASCII bytes ``PUBLISHED``.

* the second frame contains the event id for the newly published
  message.

See "Error response" below for how errors are dealt with.

QUERY
'''''
Used for querying for older events. For the ``QUERY`` request type the
next three message parts must be:

1. stream that is to be queried.

2. an optional event id, or an empty part. Restricts the earliest
   (chronologically) incoming message that we are interested in to all
   messages received after the event with the specified event id.  Note
   that this does not include the message with the specified event id.
   If this part of the message is empty, no lower restriction is made
   and messages will be returned starting from the first event ever
   seen.

3. an optional event id, or an empty part. Restricts the latest
   (chronologically) incoming message that we are interested in to all
   messages received before, or including, the event with the specified
   event id. If this part of the message is empty, no upper restriction
   is made and messages will be returned starting from the first event
   ever seen.

If you are a data structure type-of-guy you could view Gorewind as an
application that stores a bunch of named insert-ordered maps (event id
=> event) that allows querying of ranges of events based on event ids.

There are two types of responses that can be given upon a query:

* An error. See "Error response" below; or

* Multiple messages, one for each event that matches the query, followed
  by a single stop message that signals that no further messages will be
  returned. The events are returned in the same order they were
  published in.

  * Each *event message* is a multipart message consisting of three
    frames:

   * The ASCII content "EVENT".

   * The *event id* for the event in question.

   * The *event data* for the event in question.

  * The *stop message* is a single framed message consisting of the
    ASCII content ``END``. After the stop message has been sent, no
    further messages will be sent from the server.

Error response
``````````````
If anything goes wrong, a single framed message starting with the ASCII
text ``ERROR``, followed by a space (32), will be sent with the
response. This means an error occured.  The rest of message contains a
human readable (ASCII) description of the actual error that occured.
This information can be highly useful for remote clients to debug any
problems that might arise.

After an error message has been sent, no further messages will be sent
from Gorewind.

Event stream (PUB socket)
-------------------------
Every incoming event gets broadcast to all sockets connected to the
streaming socket. The streaming socket a ZeroMQ socket of type PUB.

Every message received automatically gets assigned a unique (within its
stream) event id . This event id is used for querying events (see
below). Each sent message from the streaming is a multipart message that
consists of two parts:

1. The event stream that the event belongs to.

2. The event's unique identifier within its event stream. The client
   should view this as a series of bytes.

3. The event content. This is the exact same bytes that were
   sent to the server when the event was to be published.

Developing
==========
Getting started developing `rewind` is quite straightforward. The
library uses `setuptools` and standard Python project layout for tests
etcetera.

Helping out
===========
Spelling mistakes, bad grammar, wire format improvements, test
improvements and other feature additions are all welcome. Please issue
pull requests or create an issue if you'd like to discuss it on Github.

Why the name "Gorewind"?
======================
"Gorewind" is a rewrite of "Rewind". The name "Rewind" was chosen
because:

* Rewind can look at what happened in the past and replay the events
  since then.

* It's time to rewind and rethink the way we are storing state. Disk is
  cheap.

Author
======

This package has been developed by Jens Rantil <jens.rantil@gmail.com>.
You can also reach me through snailmail at::

    Jens Rantil
    Brållunden 4
    16774 Bromma
    SWEDEN

Documentation

Overview

GoRewind is an event store server written in Go that talks ZeroMQ.

Directories

Path Synopsis
Deals with persisting events to disk and querying them.
Deals with persisting events to disk and querying them.
Contains the ZeroMQ server loop.
Contains the ZeroMQ server loop.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL