Skip to content

Commit

Permalink
Refactor to use protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
sleipnir committed Sep 30, 2024
1 parent 1012de9 commit c6f6056
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 10 deletions.
16 changes: 9 additions & 7 deletions lib/actors/actor/entity/entity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ defmodule Actors.Actor.Entity do
alias Eigr.Functions.Protocol.State.Revision

alias Spawn.Cluster.Provisioner.Scheduler
alias Spawn.Cluster.Provisioner.SpawnTask

import Spawn.Utils.Common, only: [return_and_maybe_hibernate: 1]

Expand Down Expand Up @@ -152,13 +153,14 @@ defmodule Actors.Actor.Entity do
# The same applies to asynchronous calls.
case kind do
:TASK ->
Scheduler.schedule_and_invoke(
actor_name,
invocation,
opts,
state,
&Invocation.invoke/2
)
task = %SpawnTask{
parent: actor_name,
invocation: invocation,
opts: opts,
state: state
}

Scheduler.schedule_and_invoke(task, &Invocation.invoke/2)

_ ->
Invocation.invoke({invocation, opts}, state)
Expand Down
4 changes: 4 additions & 0 deletions lib/spawn/cluster/provisioner/executor.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defprotocol Spawn.Cluster.Provisioner.Executor do
@doc "Executes a task"
def execute(task, func)
end
66 changes: 63 additions & 3 deletions lib/spawn/cluster/provisioner/scheduler.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,69 @@
defmodule Spawn.Cluster.Provisioner.Scheduler do
@moduledoc """
The `Spawn.Cluster.Provisioner.Scheduler` module is responsible for scheduling tasks and invoking functions in a distributed actor system.
It handles creating worker pools and executing functions with the given task configuration.
This module also contains an implementation of the `Executor` protocol for the `SpawnTask` struct,
defining the execution behavior for tasks in the context of provisioning actors in the cluster.
"""

alias Spawn.Cluster.Provisioner.SpawnTask
alias Spawn.Cluster.ProvisionerPoolSupervisor
import Spawn.Utils.Common, only: [build_worker_pool_name: 2]

def schedule_and_invoke(parent, invocation, opts, state, func) when is_function(func) do
build_worker_pool_name(ProvisionerPoolSupervisor, parent)
|> FLAME.call(fn -> func.({invocation, opts}, state) end)
@doc """
Defines the `Executor` protocol for the `SpawnTask` struct.
This implementation handles the execution of a given function (`func`) in the context of a task,
using the specified parent, invocation details, options (`opts`), and state.
The task is executed through a worker pool, created using the `build_worker_pool_name/2` function,
and the function is invoked with the `{invocation, opts}` tuple and the current state.
## Parameters
- `%SpawnTask{}`: The task struct containing details about the actor provisioning process.
- `func`: The function to be invoked, which takes the task's `invocation`, `opts`, and `state`.
## Returns
The result of executing the provided function within the context of the actor provisioning system.
"""
defimpl Spawn.Cluster.Provisioner.Executor, for: Spawn.Cluster.Provisioner.SpawnTask do
def execute(%SpawnTask{parent: parent, invocation: invocation, opts: opts, state: state}, func)
when is_function(func) do
build_worker_pool_name(ProvisionerPoolSupervisor, parent)
|> FLAME.call(fn -> func.({invocation, opts}, state) end)
end
end

@doc """

Check warning on line 40 in lib/spawn/cluster/provisioner/scheduler.ex

View workflow job for this annotation

GitHub Actions / Build and Test OTP 25. 26 / Elixir 1.15

redefining @doc attribute previously set at line 14
Schedules and invokes a task for actor provisioning in another k8s POD.
This function wraps the scheduling logic by leveraging the `Executor` protocol to execute the provided
function (`func`). The function is called with the `invocation`, `opts`, and `state` details encapsulated in a `SpawnTask` struct.
## Parameters
- `parent`: The parent reference used to create the worker pool for the task execution.
- `invocation`: The details of the invocation, typically containing metadata about the actor's execution.
- `opts`: Options passed along with the task, which may modify how the invocation is performed.
- `state`: The current state of the process, to be passed to the function being invoked.
- `func`: A function that will be called with the `{invocation, opts}` tuple and the current `state`.
## Example
```elixir
task = %SpawnTask{
parent: parent,
invocation: invocation,
opts: opts,
state: state
}
Spawn.Cluster.Provisioner.Scheduler.schedule_and_invoke(task, &some_function/2)
"""
def schedule_and_invoke(task, func) when is_function(func) do
Spawn.Cluster.Provisioner.Executor.execute(task, func)
end
end
3 changes: 3 additions & 0 deletions lib/spawn/cluster/provisioner/spawn_task.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
defmodule Spawn.Cluster.Provisioner.SpawnTask do
defstruct [:parent, :invocation, :opts, :state]
end

0 comments on commit c6f6056

Please sign in to comment.