Skip to content

Instantly share code, notes, and snippets.

View slashdotdash's full-sized avatar

Ben Smith slashdotdash

View GitHub Profile
@slashdotdash
slashdotdash / Vagrantfile
Created February 10, 2016 16:23 — forked from ndemonner/Vagrantfile
Sample Vagrantfile for easy Elixir-based development
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.provision "shell", inline: <<-SHELL
wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
sudo apt-get update
sudo apt-get install -y nodejs
@slashdotdash
slashdotdash / elixir-tips.md
Last active September 19, 2022 23:02
Elixir tips
@slashdotdash
slashdotdash / create_projection_versions.ex
Last active June 5, 2023 12:46
Building projections with Ecto using Commanded event handlers
defmodule Projections.Repo.Migrations.CreateProjectionVersions do
use Ecto.Migration
def change do
create table(:projection_versions, primary_key: false) do
add :projection_name, :text, primary_key: true
add :last_seen_event_id, :bigint
timestamps
end
# Aggregates are just collections of command functions, which emit events,
# and event handlers, which mutate state.
# In order to hold state, they should be also structs.
# There is no new() function because aggregates aren't supposed to appear
# out of the blue, they are always the result of a command.
# In this case, %OpenAccount{}.
defmodule Bank.Account do
defstruct [:account_number, :balance]
@slashdotdash
slashdotdash / upsert_profile.ex
Last active July 26, 2020 23:09
Upserts in Ecto using `Ecto.Multi`
defp upsert_profile(multi, source, source_uuid, profile_url) do
profile = %Profile{
source: source,
source_uuid: source_uuid,
profile: profile_url,
}
Ecto.Multi.insert(multi, source_uuid, profile, on_conflict: [set: [profile: profile_url]], conflict_target: [:source, :source_uuid])
end
@slashdotdash
slashdotdash / README.md
Last active July 21, 2017 12:29
Domain-driven design shipping example implemented using Commanded

Domain-driven design shipping example implemented using Commanded

Inspired by Peter C Marks' ddd_elixir_stage1_umbrella repo.

I've implemented the cargo event handling workflow using the approach dictated by the Commanded CQRS/ES library for Elixir.

The flow is as follows:

  1. HandlingEventController web controller constructs a TrackHandling command struct from given POST params.
  2. TrackHandling command is dispatched using the CommandRouter, which has configured the command to handler/aggregate mapping.
@slashdotdash
slashdotdash / README.md
Last active November 21, 2017 16:24
Using Commanded Ecto projections with Elixir's Registry for pub/sub read model notifications

Using Commanded Ecto projections

Example read model projections using Commanded Ecto projections where Elixir's Registry is used for pub/sub notifications of read model updates.

This alleviates the problem of async read model updates.

The command dispatcher can wait until the read model has been updated to the exact aggregate version (as returned by the dispatch command):

with {:ok, version} &lt;- Router.dispatch(register_user, include_aggregate_version: true) do
@slashdotdash
slashdotdash / cart.ex
Last active September 14, 2017 10:35
Example shopping cart aggregate using Chronik
defmodule Example.Cart do
use Chronik.Aggregate
alias Example.Cart
alias Example.DomainEvents.{CartCreated, ItemsAdded, ItemsRemoved}
defstruct [id: nil, items: %{}]
## Public API
@slashdotdash
slashdotdash / README.md
Last active March 11, 2019 10:03
Dealing with eventually consistent read model projections in Commanded

Dealing with eventually consistent read model projections in Commanded

Example

with {:ok, version} <- Router.dispatch(command, include_aggregate_version: true),
     {:ok, projection} <- wait_for_projection_version(ExampleProjection, uuid, version) do   

  # ... safely use up-to-date read model projection at expected version
 
@slashdotdash
slashdotdash / article.ex
Last active August 15, 2018 12:37
Commanded multi-entity aggregates
defmodule Article do
defstruct [:content, comments: []]
# public commands
def execute(%Article{}, %PublishArticle{content: content}) do
%ArticlePublished{content: content}
end
def execute(%Article{}, %CommentOnArticle{} = comment) do