Skip to content

Instantly share code, notes, and snippets.

@gpad
Created April 4, 2018 21:34
Show Gist options
  • Select an option

  • Save gpad/36e552c2085befc09646de6b81feac31 to your computer and use it in GitHub Desktop.

Select an option

Save gpad/36e552c2085befc09646de6b81feac31 to your computer and use it in GitHub Desktop.
Notes on les for code beam lite milano

Embrace the Memory state

mix ecto.drop && mix ecto.setup iex -S mix phx.server

{:ok, user, pid} = Les.UserEntity.create(%{username: "u1", name: "n1"})
user
pid
  • lib/les/user_entity.ex
Les.UserEntity.get(pid)
Les.UserEntity.update(pid, %{name: "gpad"})
{:ok, user} = Les.UserEntity.get(pid)
user.name

Embrace the KV

  • Show the supervisor tree in application.ex

  • Explain the EntitiesSupervisor ->

{:ok, user, pid} = Les.UserEntity.create(%{username: "kv1", name: "kv1"})
{:ok, user, pid} = Les.UserEntity.create(%{username: "kv2", name: "kv2"})

{:ok, pid1} = Les.UserEntity.find(1)
{:ok, pid2} = Les.UserEntity.find(2)
{:ok, pid3} = Les.UserEntity.find(3)

Show the code of the find in user_entity.ex that is related to supervisor.

{:ok, pid1} = Les.UserEntity.find(1)
Process.alive?(pid1)
Process.exit(pid1, :exit)
Process.alive?(pid1)

The entity is restarted because we sping the process under a supervisor. Change the restart model.

We can set something different (timeout).


Remember the supervisor in application.ex

Show the products (uncomment info)

Les.Products.all() Show the code of products (add/remove provider)

Supervisor.which_children(Les.ProductsFetcherSupervisor)

Process.exit(pid("0.442.0"), :exit) Everything is lost and restarted ...


Remember the supervisor in application.ex Show PaymentProcessorSupervisor

Now we can make a payment ...

{:ok, pid} = Les.UserEntity.find(1) Les.Products.all product = Les.Products.all |> Enum.random {:ok, cart} = Les.UserEntity.add_to_cart(pid, product.id, 1) Les.UserEntity.checkout_and_pay(pid) Les.UserEntity.invoices(pid, [])


Embrace the world

how to execute the test elixir --name [email protected] -S mix test

MIX_ENV=gpad_1 iex --name [email protected] -S mix run MIX_ENV=gpad_2 iex --name [email protected] -S mix run MIX_ENV=gpad_3 iex --name [email protected] -S mix run

:riak_core.join(:'[email protected]') :riak_core.join(:'[email protected]')

Les.ring_status()

{:ok, pid1} = Les.UserEntity.find(1) {:ok, pid2} = Les.UserEntity.find(2) {:ok, pid3} = Les.UserEntity.find(3)

Les.Products.all Les.UserEntity.add_to_cart(1, , 1)

Les.UserEntity.checkout_and_pay(1) Les.UserEntity.invoices(1, [])

Kill node 3 -> pay on node 2


Embrace Immutability

mix ecto.drop && mix ecto.setup iex -S mix phx.server

{:ok, user, pid} = Les.UserEntity.create(%{username: "u1", name: "n1"}) cart = user.cart Les.Products.all product = Les.Products.all |> Enum.random cart = Les.Carts.Cart |> Les.Repo.get(1) Les.



  1. Phoenix is not your application
  2. Embrace state outside in DB -> not only DB
  3. Sasa Juric Functionnal vs Process

Let it crash (not too much)

Articolo ADM -> Entity Activity https://queue.acm.org/detail.cfm?id=3025012

https://www.youtube.com/watch?v=MMfYXEH9KsY

Torben -> Short-lived process for small task ... Focus on protocol (MSCS)

Wait registration and do something ...

What could go wrong ...

gproc for reg & pub/sub

Timeouts, always !!!

Shoert -lived process fro samll things ..


Application

Description: POS sistem where you can:

  1. Create user
  2. Buy some "special" thing (timeout minutes)
  3. Pay ...
  4. Report !???

So create user ... think API (URL) POST /user ... GOOD, better than think to the DB schema, or which lib use. I would think on API.

Phoenix is not our application

Open the shell and think which API I want to create the user.

Les.Accounts.create_user %{name: "gino", username: "gino"}
Les.Accounts.create_user %{name: "gino", username: "gino"} # error
Les.Accounts.create_user %{name: "gino", username: "gino1"}
Les.Accounts.create_user %{name: "gino", username: "gino#{UUID.uuid4()}"}
Les.UserEntity.create(%{name: "gino", username: "gino#{UUID.uuid4()}"})

Ops I want to change the name but I need a user. I can take from previously in console but in real code or I put this logic in client or I need to reload it from server (think of a put/patch API) like

PUT /user/:id %{ name: "gino1" }

Les.Accounts.update_user user, %{name: "gino1"}

WDYT if I can move this logic inside a process ?!?

UserEntity

Start a process fro every users.

{:ok, pid1} = Les.UserEntity.start_link 1
{:ok, pid3} = Les.UserEntity.start_link 3

Les.EntitiesSupervisor.find_user

Les.Cart.add_product 1, 1, 1

Supervisor that supervise the UserEntity. When create a new user start a new process. (Chicken-and-egg dilemma).

Nice-to-have Exit after some timeout.

Cart

The cart is something inside the user

Get the product info from ETS ...

Product Fetcher

1. Is it possible don't create the worker and use only the supervisor?
2. Can I continue to use `simple_one_for_one`
3. How Can I return fake data?
product = Les.Products.all |> hd
[cart|_] = Cart |> preload(:items) |> Les.Repo.all
{:ok, pid} = Les.UserEntity.find 36
Les.UserEntity.add_to_cart(pid, product.id, 1)

TODO

  • Add some items in the carts

    • Insert Item in carts
    • Now we need to fix add_product
    • I don't undertand the chnageset almost
  • Checkout & Pay

    • Inform the Warehouse that products is reserved ...
    • Fail payment -> free product
    • Ok payment -> decrase qty
  • Start to think about distribution ...

  • Warehouse is to at the end ...

Warehouse -> External (another system) -> activities


Services/Router --->


Distribution --> Riak core


Postgres via docker -->

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment