Giter VIP home page Giter VIP logo

Comments (3)

thruflo avatar thruflo commented on July 26, 2024 1

Thanks, bear with me and I'll have a chat with the team our end. On the proxy dependencies point, yes, my first thought would be a strategy pattern (where you can configure the persistence option much like you configure the email sending library for Phoenix) but I think it depends on how you're packaging and deploying.

from massa.

sleipnir avatar sleipnir commented on July 26, 2024

Hello @thruflo, how are you? Thanks for sharing your thoughts.
As I told you in particular, we are still building these abstractions so that we can plug in different persistence backends to our Entity types.

In general, and in my personal understanding, stateful entities should have a live GenServer instance per PersistenceId, that is, whenever the client sends a request that has a persistence id X, this request will always be handled by the equivalent GenServer X instance. That way we were able to spread these instances across the cluster and still keep a healthy reference to them when we need to reference them.
In turn, this GenServer will have to deal with the entire lifecycle of the function state for that given persistenceId, that is, things like hydration (activation), persistence, snapshots, and queries should be the responsibility of this GenServer.
But in order to abstract these concepts and implement different types of storage, we will have to make this GenServer a client (has a dependency) of a module that knows how to do all these things (recover and save entities).
And this is where I think there are two possible approaches in Elixir to deal with this, namely Behaviors and Protocols.
We can define a Protocol and implementers can implement this protocol for the type of entity of interest (EventSourced, CRDT, KV, and etc..), the same goes for if we are going to use a Behaviour, and so when we create the GenServer we can query the configuration and inject the equivalent implementation into the GenServer module as part of its internal state. Example with Behaviour.

defmodule EventSourcedEntityActor do
  use GenServer
  def init(%{persistor: persistor, persistence_id: x} = initial_state) do
    Process.flag(:trap_exit, true)
    .....
    {:ok, initial_state}
  end

  def handle_call({:persist_event, event}, from, %{persistor: persistor, persistence_id: id} = state)
    persistor.save(id, event)
    ....
  end

  def handle_call(:snapshot, from, %{persistor: persistor, persistence_id: id} = state)
    persistor.snapshot(id, state)
    ....
  end

  def terminate(_reason, %{persistor: persistor, persistence_id: id} = state)
    persistor.snapshot(id, state)
  end
  ....
end

So basically we need to start by defining the Behavior or Protocol contract.

After that, another question would be how to manage these dependencies in the Proxy, that is, we are going to add directly to the proxy dependencies all possible implementations that we have, and this leads to an increasingly larger Proxy with more dependencies and possibly consuming more resources, Or is there any alternative to this scenario? I don't know in Elixir or Erlang any plugin pattern, or library, that is viable for our scenario, but I'm researching it.
In Cloudstate/AkkaServeless they solved this problem by generating a specific binary for each type of storage used (although they could have solved this with dynamic classpath, but due to the use of GraalVM this would not be possible either).

Anyway, I tried to give you some context, any new ideas would be welcome as we are still in the design phase of this item.

from massa.

sleipnir avatar sleipnir commented on July 26, 2024

Thanks, bear with me and I'll have a chat with the team our end. On the proxy dependencies point, yes, my first thought would be a strategy pattern (where you can configure the persistence option much like you configure the email sending library for Phoenix) but I think it depends on how you're packaging and deploying.

Yes, the idea is that the adapter itself is located via the runtime configuration, so when the proxy is deployed we take the adapter implementation via the configuration and when we start GenServer we pass it on

from massa.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.