Crowdhailer

Crowdhailer

Creator of Raxx

Summary

Durable, globally unique processes (Entites) are created by controlling side effects.
(In short side effects are deferred until the state change of the entity has been committed to storage).

The purpose of an entity is to handle data that must be strongly consistent within a given execution context.

Example (as of 0.2.0)

Entity behaviour

defmodule MyApp.Counter do
  @behaviour Pachyderm.Entity

  alias MyApp.Counter.{Increment, ...}
  alias MyApp.Counter.{Increased, ...}

  def init() do
    %{count: 0}
  end

  def handle(%Increment{}, %{count: count}) do
    events = [%Increased{amount: 1}]

    if count == 9 do
      effects = [{MyApp.AdminMailer, %{threshold: 10}}]
      {:ok, {events, effects}}
    else
      {:ok, events}
    end
  end

  def update(%Increased{amount: amount}, state = %{count: current}) do
    %{state | count: current + amount}
  end
end

Calling Entities

type = MyApp.Counter
id = UUID.uuid4()
reference = {type, id}

{:ok, state} = Pachyderm.call(reference, %Increment{})
# => {:ok, %{count: 1}}

Design notes

A detailed discussion of why this API was chosen and further examples is available in the project README.

Why

The single global process is very easy to reason about, but has many pitfalls.
The dangers of the single global process.
Pachyderm tries to rescue this simple model by offering a standard way of managing some of the pitfalls.

Prior Art

The description of this project is quite difficult because there are lots of related but different approaches to this problem.

Other terminology includes:

Showing Posts 1 to 10

Qqwy

Qqwy

TypeCheck Core Team

Very cool!

What is your approach in the face of netsplits?
EDIT: I’ve read through the README, and it seems, if I interpret the explanation in the deferred side-effects section correctly, that Pachyderm defers netsplit handling to the storage layer: The first event to be ‘committed to storage’ wins, and at that time other events that were based on a stale state will be dropped (and you can possibly retry them manually).

‘Commited to storage’ is not a very clear thing to say. What is the storage? What does it mean to be commited to it?
If the storage is distributed, then multiple nodes might both save things thinking they are the first. On the other hand, if the storage is only in one single place, you create a single point of failure and a bottleneck (since all events go through this storage).

tristan

tristan

Rebar3 Core Team

It says it is based on Orleans so hopefully a safe assumption that it does storage similarly. If this is the case then it writes an etag with the state of a grain to storage when it saves state and uses the etag it read in on start to compare against the one currently in the store when doing the write. if the etags don’t match then it fails.

In sql this looks like https://github.com/erleans/erleans/blob/master/priv/blob_provider.sql#L60 for an update. This is from my project Erleans that is also based on Orleans.

Crowdhailer

Crowdhailer OP

Creator of Raxx

Committed to storage depends on the storage being used. At the moment it means that a Database transaction has completed.

However an append only log is something that can be implemented multiple ways, it could be written to kafka for example.

If the storage is distributed, then multiple nodes might both save things thinking they are the first
That would be a bug in the append only log. The log must offer a strong consistency API, and only consider the write to have succeeded once they are sure that only their write is definitely the next entry in the log.

Qqwy

Qqwy

TypeCheck Core Team

Thank you for your response!

Would it be correct to say that ‘the database’, ‘Kafka’ or whatever other thing that manages the append-only log is a bottleneck and failure-point for the Pachyderm system? And that Pachyderm therefore scales as well as the technology used to manage the append-only log can scale?

tristan

tristan

Rebar3 Core Team

Ah, so pachyderm is based on storing an event log instead of doing state like I described?

Crowdhailer

Crowdhailer OP

Creator of Raxx

Yes, as much as any coordination point for strong consistency MUST BE (by definition) a single point of failure. Pachyderm’s goal is for easy to work with strong consistency.

There are no consistency guarantees between entities. Pachyderm run each entity concurrently and so is concurrent to the maximum possible degree. There is nothing stopping a log also being fully partitioned by entity.

Crowdhailer

Crowdhailer OP

Creator of Raxx

Yes Pachyderm stores events, I wasn’t sure if you were originally talking about inside the storage layer.

pma

pma

GitHub - rabbitmq/ra: A Multi-Raft implementation for Erlang and Elixir that strives to be efficient and make it easier to use multiple Raft clusters in a single system. · GitHub implements Raft for consensus and allows defining side-effects that run on the leader only. Using it with disk_log as storage layer for an event sourced system

Crowdhailer

Crowdhailer OP

Creator of Raxx

Ra looks interesting. At first I thought It might be cool to make an alternative Log storage. for Pachyderm using it.

However it could be even more useful, because it handles side effects as data in much the same way as Pachyderm. Just finished watching this talk. Which is really informative.

wanton7

wanton7

Instead of presenting virtual actors as actors would it be actually make more sense to create virtual actors similarly how dapr.io is doing it by treating actor calls basically as web requests. This way even reentrancy could be supported in Elixir for virtual actors.

Where Next? Top

Trending in Announcing Top

wojtekmach
Hey everyone! Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
fuelen
Hi all! I want to present a small library which provides a mix task for generating an Entity-Relationship Diagram for Ecto schemas. You...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews