All Projects â†’ NFIBrokerage â†’ spear

NFIBrokerage / spear

Licence: Apache-2.0 license
A sharp EventStoreDB v20+ client backed by Mint 😋

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to spear

domain
A dependency-free package to help building a business domain layer
Stars: ✭ 33 (-35.29%)
Mutual labels:  event-sourcing
engine
Engine provides you all the capabilities to build an Event sourced application.
Stars: ✭ 35 (-31.37%)
Mutual labels:  event-sourcing
eda-tutorial
Event-Driven Tutorial for Distributed Data with CQRS and Event Sourcing
Stars: ✭ 49 (-3.92%)
Mutual labels:  event-sourcing
ddes
JS/TypeScript framework for Distributed Event Sourcing & CQRS
Stars: ✭ 28 (-45.1%)
Mutual labels:  event-sourcing
node-event-storage
An optimized event store for node.js
Stars: ✭ 29 (-43.14%)
Mutual labels:  event-sourcing
node-cqrs-saga
Node-cqrs-saga is a node.js module that helps to implement the sagas in cqrs. It can be very useful as domain component if you work with (d)ddd, cqrs, eventdenormalizer, host, etc.
Stars: ✭ 59 (+15.69%)
Mutual labels:  event-sourcing
chronicle
An event sourced CQRS framework for Rust
Stars: ✭ 36 (-29.41%)
Mutual labels:  event-sourcing
fmodel-ts
Functional Domain Modeling with Typescript
Stars: ✭ 41 (-19.61%)
Mutual labels:  event-sourcing
JSpeak
A Text to Speech Reader Front-end that Reads from the Clipboard and with Exceptionable Features
Stars: ✭ 16 (-68.63%)
Mutual labels:  mint
akka-persistence-gcp-datastore
akka-persistence-gcp-datastore is a journal and snapshot store plugin for akka-persistence using google cloud firestore in datastore mode.
Stars: ✭ 18 (-64.71%)
Mutual labels:  event-sourcing
TimeWriter
An online collaborative text editor based on event sourcing architecture.
Stars: ✭ 41 (-19.61%)
Mutual labels:  event-sourcing
muon-java
Muon Core for the JVM. APIs and Microservices taken to the next level
Stars: ✭ 18 (-64.71%)
Mutual labels:  event-sourcing
banku
Go event sourcing with Kafka, example project
Stars: ✭ 29 (-43.14%)
Mutual labels:  event-sourcing
es-emergency-call
Struggling with CQRS, A+ES, DDD? We can help you!
Stars: ✭ 26 (-49.02%)
Mutual labels:  event-sourcing
eventuous
Minimalistic Event Sourcing library for .NET
Stars: ✭ 236 (+362.75%)
Mutual labels:  event-sourcing
Learning.EventStore
A framework for CQRS, Eventsourcing, and messaging that uses Redis pub/sub for messaging and offers event persistence in Redis, SQL Server, or PostgreSQL.
Stars: ✭ 58 (+13.73%)
Mutual labels:  event-sourcing
e-shop
Sample Spring Cloud microservices e-shop.
Stars: ✭ 48 (-5.88%)
Mutual labels:  event-sourcing
stem
Event sourcing framework based on ZIO and pluggable runtime (currently working with Akka cluster)
Stars: ✭ 22 (-56.86%)
Mutual labels:  event-sourcing
firebase-event-sourcing
Event Sourcing + CQRS + DDD for Firebase
Stars: ✭ 14 (-72.55%)
Mutual labels:  event-sourcing
awesome-talks
Awesome talks about event sourcing, cqrs, microservices, funcional programming ...
Stars: ✭ 23 (-54.9%)
Mutual labels:  event-sourcing

Spear

CI Coverage Status hex.pm version hex.pm license Last Updated

A sharp EventStoreDB 20+ client backed by mint 😋

FAQ

What's EventStoreDB?

EventStoreDB is a database designed for Event Sourcing. Instead of tables with rows and columns, EventStoreDB stores information in immutable events which are appended to streams.

Why the name "spear"?

  1. best gum flavor
  2. obligatory programmer reference to ancient greek, roman, or egyptian history
  3. sounds cool 😎

Backed by... Mint?

elixir-mint/mint is a functional HTTP client which supports HTTP2.

gRPC is pretty thin protocol built on top of HTTP/2. Practically speaking, gRPC just adds some well-known headers and a message format that allows messages to not be aligned with HTTP2 DATA frames. It's relatively trivial to implement gRPC with a nice HTTP2 library like mint 🙂.

Why not elixir-grpc/grpc?

That project looks good but it depends on :gun which doesn't play nice with other dependencies1. It also provides a server and client implementation in one library. This library only needs a client.

Does TLS work?

Yep! As of v0.1.3, custom and public CAs may be used for encrypted connections.

Does this work with EventStore <20?

Sadly no. This library only provides a gRPC client which showed up in EventStoreDB 20+. If you're looking for a similarly fashioned TCP client, NFIBrokerage uses exponentially/extreme extensively in production (specifically the v1.0.0 branch). Spear and Extreme have compatible dependencies and similar styles of making connections.

How many dependencies are we talking here?

Spear's reliance on Mint and :gpb give it a somewhat small dependency tree:

$ mix deps.tree --only prod
spear
├── connection ~> 1.0 (Hex package)
├── event_store_db_gpb_protobufs ~> 2.0 (Hex package)
│   └── gpb ~> 4.0 (Hex package)
├── gpb ~> 4.0 (Hex package)
├── jason >= 0.0.0 (Hex package)
└── mint ~> 1.0 (Hex package)

(And jason is optional!)

How close is this to being able to be used?

We @NFIBrokerage already use Spear for some production connections to Event Store Cloud. See the roadmap in #7 with the plans for reaching the v1.0.0 release.

Installation

Add :spear to your mix dependencies in mix.exs

def deps do
  [
    {:spear, "~> 1.0"},
    # If you want to encode events as JSON, :jason is a great library for
    # encoding and decoding and works out-of-the-box with spear.
    # Any JSON (de)serializer should work though, so you don't *need* to add
    # :jason to your dependencies.
    {:jason, "~> 1.0"},
    # If you're connecting to an EventStoreDB with a TLS certificate signed
    # by a public Certificate Authority (CA), include :castore
    {:castore, ">= 0.0.0"}
  ]
end

Usage

Making a connection...

Familiar with Ecto.Repo? It lets you write a database connection like a module

# note this is for illustration purposes and NOT directly related to Spear
# lib/my_app/repo.ex
defmodule MyApp.Repo do
  use Ecto.Repo,
    otp_app: :my_app,
    adapter: Ecto.Adapters.Postgres
end

and then configure it with application-config (config/*.exs)

# note this is for illustration purposes and NOT directly related to Spear
# config/config.exs
config :my_app, MyApp.Repo,
  url: "ecto://postgres:postgres@localhost/my_database"

Spear lets you do the same with a connection to the EventStoreDB:

# lib/my_app/event_store_db_client.ex
defmodule MyApp.EventStoreDbClient do
  use Spear.Client,
    otp_app: :my_app
end

and configure it,

# config/config.exs
config :my_app, MyApp.EventStoreDbClient,
  connection_string: "esdb://localhost:2113"

add it to your application's supervision tree in lib/my_app/application.ex

# lib/my_app/application.ex
defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      MyApp.EventStoreDbClient
    ]
    
    Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)
  end
end
Or connecting in IEx...

A Spear.Connection is just a regular ole' GenServer with a default of pulling configuration from application-config. You can start a Spear.Connection like any other process, even in IEx! Plus you can provide the configuration straight to the Spear.Connection.start_link/1 function.

Let's use the new Mix.install/1 function from Elixir 1.12 to try out Spear. Say that you have an EventStoreDB instance running locally with the --insecure option.

iex> Mix.install([:spear, :jason])
# a bunch of installation text here
:ok
iex> {:ok, conn} = Spear.Connection.start_link(connection_string: "esdb://localhost:2113")
{:ok, #PID<0.1518.0>}

And we're up and running reading and writing events!

Reading and writing streams...

Now that we have a connection process (we'll call it conn), let's read and write some events!

iex> event = Spear.Event.new("IExAndSpear", %{"hello" => "world"})
%Spear.Event{
  body: %{"hello" => "world"},
  id: "9e3a8bcf-0c22-4a38-85c6-2054a0342ec8",
  metadata: %{content_type: "application/json", custom_metadata: ""},
  type: "IExAndSpear"
}
iex> [event] |> Spear.append(conn, "MySpearDemo")
:ok
iex> Spear.stream!(conn, "MySpearDemo")
#Stream<[
  enum: #Function<62.80860365/2 in Stream.unfold/2>,
  funs: [#Function<48.80860365/1 in Stream.map/2>]
]>
iex> Spear.stream!(conn, "MySpearDemo") |> Enum.to_list()
[
  %Spear.Event{
    body: %{"hello" => "world"},
    id: "9e3a8bcf-0c22-4a38-85c6-2054a0342ec8",
    metadata: %{
      commit_position: 18446744073709551615,
      content_type: "application/json",
      created: ~U[2021-04-12 20:05:17.757215Z],
      custom_metadata: "",
      prepare_position: 18446744073709551615,
      stream_name: "MySpearDemo",
      stream_revision: 0
    },
    type: "IExAndSpear"
  }
]

Spear uses Elixir Streams to provide a flexible and efficient interface for EventStoreDB streams.

iex> Stream.repeatedly(fn -> Spear.Event.new("TinyEvent", %{}) end)
#Function<51.80860365/2 in Stream.repeatedly/1>
iex> Stream.repeatedly(fn -> Spear.Event.new("TinyEvent", %{}) end) |> Stream.take(10_000) |> Spear.append(conn, "LongStream")
:ok
iex> Spear.stream!(conn, "LongStream")
#Stream<[
  enum: #Function<62.80860365/2 in Stream.unfold/2>,
  funs: [#Function<48.80860365/1 in Stream.map/2>]
]>
iex> Spear.stream!(conn, "LongStream") |> Enum.count
10000

And that's the basics! Check out the Spear documentation on hex. Interested in writing efficient event-processing pipelines and topologies with EventStoreDB via GenStage and Broadway producers? Check out Volley.

Footnotes

  1. #66 ↩

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].