From f17d5929831aa1e7c22028bdbb6b031a3093ec12 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 27 Sep 2024 20:17:38 -0300 Subject: [PATCH 01/34] Create new Actor kind --- .../functions/protocol/actors/actor.proto | 199 +++++++++--------- 1 file changed, 102 insertions(+), 97 deletions(-) diff --git a/priv/protos/eigr/functions/protocol/actors/actor.proto b/priv/protos/eigr/functions/protocol/actors/actor.proto index 6d015d4f..d49b3a60 100644 --- a/priv/protos/eigr/functions/protocol/actors/actor.proto +++ b/priv/protos/eigr/functions/protocol/actors/actor.proto @@ -7,164 +7,169 @@ import "google/protobuf/any.proto"; option java_package = "io.eigr.functions.protocol.actors"; option go_package = "github.com/eigr/go-support/eigr/actors;actors"; - -message Registry { - map actors = 1; -} +message Registry { map actors = 1; } message ActorSystem { - string name = 1; - Registry registry = 2; + string name = 1; + Registry registry = 2; } // A strategy for save state. message ActorSnapshotStrategy { - oneof strategy { - // the timeout strategy. - TimeoutStrategy timeout = 1; - } + oneof strategy { + // the timeout strategy. + TimeoutStrategy timeout = 1; + } } // A strategy which a user function's entity is passivated. message ActorDeactivationStrategy { - oneof strategy { - // the timeout strategy. - TimeoutStrategy timeout = 1; - } + oneof strategy { + // the timeout strategy. + TimeoutStrategy timeout = 1; + } } -// A strategy based on a timeout. +// A strategy based on a timeout. message TimeoutStrategy { - // The timeout in millis - int64 timeout = 1; + // The timeout in millis + int64 timeout = 1; } -// A action represents an action that the user can perform on an Actor. +// A action represents an action that the user can perform on an Actor. // Actions in supporting languages are represented by functions or methods. -// An Actor action has nothing to do with the semantics of Actions in a CQRS/EventSourced system. -// It just represents an action that supporting languages can invoke. +// An Actor action has nothing to do with the semantics of Actions in a +// CQRS/EventSourced system. It just represents an action that supporting +// languages can invoke. message Action { - // The name of the function or method in the supporting language that has been registered in Ator. - string name = 1; + // The name of the function or method in the supporting language that has been + // registered in Ator. + string name = 1; } -// A FixedTimerAction is similar to a regular Action, its main differences are that it is scheduled to run at regular intervals -// and only takes the actor's state as an argument. -// Timer Actions are good for executing loops that manipulate the actor's own state. -// In Elixir or other languages in BEAM it would be similar to invoking Process.send_after(self(), atom, msg, timeout) +// A FixedTimerAction is similar to a regular Action, its main differences are +// that it is scheduled to run at regular intervals and only takes the actor's +// state as an argument. Timer Actions are good for executing loops that +// manipulate the actor's own state. In Elixir or other languages in BEAM it +// would be similar to invoking Process.send_after(self(), atom, msg, timeout) message FixedTimerAction { - // The time to wait until the action is triggered - int32 seconds = 1; + // The time to wait until the action is triggered + int32 seconds = 1; - // See Action description Above - Action action = 2; + // See Action description Above + Action action = 2; } message ActorState { - map tags = 1; - google.protobuf.Any state = 2; + map tags = 1; + google.protobuf.Any state = 2; } -// Metadata represents a set of key-value pairs that can be used to +// Metadata represents a set of key-value pairs that can be used to // provide additional information about an Actor. message Metadata { - // A channel group represents a way to send actions to various actors - // that belong to a certain semantic group. Following the Pub-Sub pattern. - repeated Channel channel_group = 1; + // A channel group represents a way to send actions to various actors + // that belong to a certain semantic group. Following the Pub-Sub pattern. + repeated Channel channel_group = 1; - map tags = 2; + map tags = 2; } -// Represents a Pub-Sub binding, where a actor can be subscribed to a channel +// Represents a Pub-Sub binding, where a actor can be subscribed to a channel // and map a specific action to a specific topic if necessary // if the action is not informed, the default action will be "receive". message Channel { - string topic = 1; - string action = 2; + string topic = 1; + string action = 2; } // The type that defines the runtime characteristics of the Actor. -// Regardless of the type of actor it is important that +// Regardless of the type of actor it is important that // all actors are registered during the proxy and host initialization phase. enum Kind { - // When no type is informed, the default to be assumed will be the Named pattern. - UNKNOW_KIND = 0; - - // NAMED actors as the name suggests have only one real instance of themselves running - // during their entire lifecycle. That is, they are the opposite of the UNNAMED type Actors. - NAMED = 1; - - // UNNAMED actors are used to create children of this based actor at runtime - UNNAMED = 2; - - // Pooled Actors are similar to Unnamed actors, but unlike them, - // their identifying name will always be the one registered at the system initialization stage. - // The great advantage of Pooled actors is that they have multiple instances of themselves - // acting as a request service pool. - // Pooled actors are also stateless actors, that is, they will not have their - // in-memory state persisted via Statesstore. This is done to avoid problems - // with the correctness of the stored state. - // Pooled Actors are generally used for tasks where the Actor Model would perform worse - // than other concurrency models and for tasks that do not require state concerns. - // Integration flows, data caching, proxies are good examples of use cases - // for this type of Actor. - POOLED = 3; - - // Reserved for future use - PROXY = 4; + // When no type is informed, the default to be assumed will be the Named + // pattern. + UNKNOW_KIND = 0; + + // NAMED actors as the name suggests have only one real instance of themselves + // running during their entire lifecycle. That is, they are the opposite of + // the UNNAMED type Actors. + NAMED = 1; + + // UNNAMED actors are used to create children of this based actor at runtime + UNNAMED = 2; + + // Pooled Actors are similar to Unnamed actors, but unlike them, + // their identifying name will always be the one registered at the system + // initialization stage. The great advantage of Pooled actors is that they + // have multiple instances of themselves acting as a request service pool. + // Pooled actors are also stateless actors, that is, they will not have their + // in-memory state persisted via Statesstore. This is done to avoid problems + // with the correctness of the stored state. + // Pooled Actors are generally used for tasks where the Actor Model would + // perform worse than other concurrency models and for tasks that do not + // require state concerns. Integration flows, data caching, proxies are good + // examples of use cases for this type of Actor. + POOLED = 3; + + // Reserved for future use + PROXY = 4; + + TASK = 5; } message ActorSettings { - // Indicates the type of Actor to be configured. - Kind kind = 1; + // Indicates the type of Actor to be configured. + Kind kind = 1; - // Indicates whether an actor's state should be persisted in a definitive store. - bool stateful = 2; + // Indicates whether an actor's state should be persisted in a definitive + // store. + bool stateful = 2; - // Snapshot strategy - ActorSnapshotStrategy snapshot_strategy = 3; + // Snapshot strategy + ActorSnapshotStrategy snapshot_strategy = 3; - // Deactivate strategy - ActorDeactivationStrategy deactivation_strategy = 4; + // Deactivate strategy + ActorDeactivationStrategy deactivation_strategy = 4; - // When kind is POOLED this is used to define minimun actor instances - int32 min_pool_size = 5; + // When kind is POOLED this is used to define minimun actor instances + int32 min_pool_size = 5; - // When kind is POOLED this is used to define maximum actor instances - int32 max_pool_size = 6; + // When kind is POOLED this is used to define maximum actor instances + int32 max_pool_size = 6; } message ActorId { - // The name of a Actor Entity. - string name = 1; + // The name of a Actor Entity. + string name = 1; - // Name of a ActorSystem - string system = 2; + // Name of a ActorSystem + string system = 2; - // When the Actor is of the Unnamed type, - // the name of the parent Actor must be informed here. - string parent = 3; + // When the Actor is of the Unnamed type, + // the name of the parent Actor must be informed here. + string parent = 3; } message Actor { - // Actor Identification - ActorId id = 1; + // Actor Identification + ActorId id = 1; - // A Actor state. - ActorState state = 2; + // A Actor state. + ActorState state = 2; - // Actor metadata - Metadata metadata = 6; + // Actor metadata + Metadata metadata = 6; - // Actor settings. - ActorSettings settings = 3; + // Actor settings. + ActorSettings settings = 3; - // The actions registered for an actor - repeated Action actions = 4; + // The actions registered for an actor + repeated Action actions = 4; - // The registered timer actions for an actor. - repeated FixedTimerAction timer_actions = 5; + // The registered timer actions for an actor. + repeated FixedTimerAction timer_actions = 5; } \ No newline at end of file From f21cc87a192b624c338d18ebed92227c0a0ceaea Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 27 Sep 2024 23:04:37 -0300 Subject: [PATCH 02/34] Add example using new topology section for ActorHost CRD --- examples/topology/host.yaml | 31 +++++++++++++++++++++++++++++++ examples/topology/system.yaml | 15 +++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 examples/topology/host.yaml create mode 100644 examples/topology/system.yaml diff --git a/examples/topology/host.yaml b/examples/topology/host.yaml new file mode 100644 index 00000000..8d1a08f6 --- /dev/null +++ b/examples/topology/host.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: spawn-eigr.io/v1 +kind: ActorHost +metadata: + name: topology-example # Mandatory. Name of the Node containing Actor Host Functions + namespace: default # Optional. Default namespace is "default" + annotations: + # Mandatory. Name of the ActorSystem declared in ActorSystem CRD + spawn-eigr.io/actor-system: spawn-system +spec: + host: + image: eigr/spawn-springboot-examples:0.5.5 # Mandatory + topology: + nodeSelector: + gpu: "false" + tolerations: + - key: "cpu-machines" + operator: "Exists" + effect: "NoExecute" + # this configure podTemplate for Task Actors + taskActors: + - parentName: Jose + nodeSelector: + gpu: "true" + tolerations: + - key: "gpu-machines" + operator: "Exists" + effect: "NoExecute" + - parentName: Franchesco + nodeSelector: + beam: "true" diff --git a/examples/topology/system.yaml b/examples/topology/system.yaml new file mode 100644 index 00000000..8983ccee --- /dev/null +++ b/examples/topology/system.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: spawn-eigr.io/v1 +kind: ActorSystem +metadata: + name: spawn-system # Mandatory. Name of the state store + namespace: default # Optional. Default namespace is "default" +spec: + externalInvocation: + enabled: "true" + externalConnectorRef: invocation-connection-ref-secret + statestore: + type: MySql + credentialsSecretRef: mysql-connection-secret # The secret containing connection params + pool: # Optional + size: "10" From 4724e0d44ef4817de4fb6deff01624ca1c08ee07 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 27 Sep 2024 23:05:37 -0300 Subject: [PATCH 03/34] Added new actor kind --- compile-pb.sh | 4 +- .../functions/protocol/actors/actor.pb.ex | 142 ++++++----- .../protocol/actors/extensions.pb.ex | 7 +- .../protocol/actors/healthcheck.pb.ex | 25 +- .../functions/protocol/actors/protocol.pb.ex | 221 +++++++++--------- .../functions/protocol/actors/state.pb.ex | 12 +- mix.lock | 2 + spawn_proxy/proxy/mix.exs | 1 + 8 files changed, 203 insertions(+), 211 deletions(-) diff --git a/compile-pb.sh b/compile-pb.sh index 787be7f1..8b87e3c2 100755 --- a/compile-pb.sh +++ b/compile-pb.sh @@ -4,7 +4,7 @@ set -o nounset set -o errexit set -o pipefail -protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib/spawn/grpc --proto_path=priv/protos/grpc/ priv/protos/grpc/reflection/v1alpha/reflection.proto +#protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib/spawn/grpc --proto_path=priv/protos/grpc/ priv/protos/grpc/reflection/v1alpha/reflection.proto # protoc --elixir_out=gen_descriptors=true:./lib/spawn/google/protobuf --proto_path=priv/protos/google/protobuf priv/protos/google/protobuf/any.proto # protoc --elixir_out=gen_descriptors=true:./lib/spawn/google/protobuf --proto_path=priv/protos/google/protobuf priv/protos/google/protobuf/empty.proto @@ -48,7 +48,7 @@ for file in $PROTOS; do --include-path=$BASE_PATH/priv/protos/ \ --include-path=./priv/protos/google/protobuf \ --include-path=./priv/protos/google/api \ - --plugins=ProtobufGenerate.Plugins.GRPCWithOptions \ + --plugin=ProtobufGenerate.Plugins.GRPCWithOptions \ --one-file-per-module \ $BASE_PATH/$file done \ No newline at end of file diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex index 747f9206..c2a95432 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex @@ -1,6 +1,6 @@ defmodule Eigr.Functions.Protocol.Actors.Kind do @moduledoc false - use Protobuf, enum: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, enum: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -36,6 +36,12 @@ defmodule Eigr.Functions.Protocol.Actors.Kind do number: 4, options: nil, __unknown_fields__: [] + }, + %Google.Protobuf.EnumValueDescriptorProto{ + name: "TASK", + number: 5, + options: nil, + __unknown_fields__: [] } ], options: nil, @@ -45,16 +51,17 @@ defmodule Eigr.Functions.Protocol.Actors.Kind do } end - field(:UNKNOW_KIND, 0) - field(:NAMED, 1) - field(:UNNAMED, 2) - field(:POOLED, 3) - field(:PROXY, 4) + field :UNKNOW_KIND, 0 + field :NAMED, 1 + field :UNNAMED, 2 + field :POOLED, 3 + field :PROXY, 4 + field :TASK, 5 end defmodule Eigr.Functions.Protocol.Actors.Registry.ActorsEntry do @moduledoc false - use Protobuf, map: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, map: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -100,7 +107,6 @@ defmodule Eigr.Functions.Protocol.Actors.Registry.ActorsEntry do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -112,13 +118,13 @@ defmodule Eigr.Functions.Protocol.Actors.Registry.ActorsEntry do } end - field(:key, 1, type: :string) - field(:value, 2, type: Eigr.Functions.Protocol.Actors.Actor) + field :key, 1, type: :string + field :value, 2, type: Eigr.Functions.Protocol.Actors.Actor end defmodule Eigr.Functions.Protocol.Actors.Registry do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -183,7 +189,6 @@ defmodule Eigr.Functions.Protocol.Actors.Registry do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -205,16 +210,15 @@ defmodule Eigr.Functions.Protocol.Actors.Registry do } end - field(:actors, 1, + field :actors, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.Registry.ActorsEntry, map: true - ) end defmodule Eigr.Functions.Protocol.Actors.ActorSystem do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -262,13 +266,13 @@ defmodule Eigr.Functions.Protocol.Actors.ActorSystem do } end - field(:name, 1, type: :string) - field(:registry, 2, type: Eigr.Functions.Protocol.Actors.Registry) + field :name, 1, type: :string + field :registry, 2, type: Eigr.Functions.Protocol.Actors.Registry end defmodule Eigr.Functions.Protocol.Actors.ActorSnapshotStrategy do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -308,14 +312,14 @@ defmodule Eigr.Functions.Protocol.Actors.ActorSnapshotStrategy do } end - oneof(:strategy, 0) + oneof :strategy, 0 - field(:timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0) + field :timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0 end defmodule Eigr.Functions.Protocol.Actors.ActorDeactivationStrategy do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -355,14 +359,14 @@ defmodule Eigr.Functions.Protocol.Actors.ActorDeactivationStrategy do } end - oneof(:strategy, 0) + oneof :strategy, 0 - field(:timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0) + field :timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0 end defmodule Eigr.Functions.Protocol.Actors.TimeoutStrategy do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -396,12 +400,12 @@ defmodule Eigr.Functions.Protocol.Actors.TimeoutStrategy do } end - field(:timeout, 1, type: :int64) + field :timeout, 1, type: :int64 end defmodule Eigr.Functions.Protocol.Actors.Action do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -435,12 +439,12 @@ defmodule Eigr.Functions.Protocol.Actors.Action do } end - field(:name, 1, type: :string) + field :name, 1, type: :string end defmodule Eigr.Functions.Protocol.Actors.FixedTimerAction do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -488,13 +492,13 @@ defmodule Eigr.Functions.Protocol.Actors.FixedTimerAction do } end - field(:seconds, 1, type: :int32) - field(:action, 2, type: Eigr.Functions.Protocol.Actors.Action) + field :seconds, 1, type: :int32 + field :action, 2, type: Eigr.Functions.Protocol.Actors.Action end defmodule Eigr.Functions.Protocol.Actors.ActorState.TagsEntry do @moduledoc false - use Protobuf, map: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, map: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -540,7 +544,6 @@ defmodule Eigr.Functions.Protocol.Actors.ActorState.TagsEntry do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -552,13 +555,13 @@ defmodule Eigr.Functions.Protocol.Actors.ActorState.TagsEntry do } end - field(:key, 1, type: :string) - field(:value, 2, type: :string) + field :key, 1, type: :string + field :value, 2, type: :string end defmodule Eigr.Functions.Protocol.Actors.ActorState do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -637,7 +640,6 @@ defmodule Eigr.Functions.Protocol.Actors.ActorState do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -659,18 +661,17 @@ defmodule Eigr.Functions.Protocol.Actors.ActorState do } end - field(:tags, 1, + field :tags, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.ActorState.TagsEntry, map: true - ) - field(:state, 2, type: Google.Protobuf.Any) + field :state, 2, type: Google.Protobuf.Any end defmodule Eigr.Functions.Protocol.Actors.Metadata.TagsEntry do @moduledoc false - use Protobuf, map: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, map: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -716,7 +717,6 @@ defmodule Eigr.Functions.Protocol.Actors.Metadata.TagsEntry do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -728,13 +728,13 @@ defmodule Eigr.Functions.Protocol.Actors.Metadata.TagsEntry do } end - field(:key, 1, type: :string) - field(:value, 2, type: :string) + field :key, 1, type: :string + field :value, 2, type: :string end defmodule Eigr.Functions.Protocol.Actors.Metadata do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -813,7 +813,6 @@ defmodule Eigr.Functions.Protocol.Actors.Metadata do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -835,22 +834,20 @@ defmodule Eigr.Functions.Protocol.Actors.Metadata do } end - field(:channel_group, 1, + field :channel_group, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.Channel, json_name: "channelGroup" - ) - field(:tags, 2, + field :tags, 2, repeated: true, type: Eigr.Functions.Protocol.Actors.Metadata.TagsEntry, map: true - ) end defmodule Eigr.Functions.Protocol.Actors.Channel do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -898,13 +895,13 @@ defmodule Eigr.Functions.Protocol.Actors.Channel do } end - field(:topic, 1, type: :string) - field(:action, 2, type: :string) + field :topic, 1, type: :string + field :action, 2, type: :string end defmodule Eigr.Functions.Protocol.Actors.ActorSettings do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1008,26 +1005,24 @@ defmodule Eigr.Functions.Protocol.Actors.ActorSettings do } end - field(:kind, 1, type: Eigr.Functions.Protocol.Actors.Kind, enum: true) - field(:stateful, 2, type: :bool) + field :kind, 1, type: Eigr.Functions.Protocol.Actors.Kind, enum: true + field :stateful, 2, type: :bool - field(:snapshot_strategy, 3, + field :snapshot_strategy, 3, type: Eigr.Functions.Protocol.Actors.ActorSnapshotStrategy, json_name: "snapshotStrategy" - ) - field(:deactivation_strategy, 4, + field :deactivation_strategy, 4, type: Eigr.Functions.Protocol.Actors.ActorDeactivationStrategy, json_name: "deactivationStrategy" - ) - field(:min_pool_size, 5, type: :int32, json_name: "minPoolSize") - field(:max_pool_size, 6, type: :int32, json_name: "maxPoolSize") + field :min_pool_size, 5, type: :int32, json_name: "minPoolSize" + field :max_pool_size, 6, type: :int32, json_name: "maxPoolSize" end defmodule Eigr.Functions.Protocol.Actors.ActorId do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1089,14 +1084,14 @@ defmodule Eigr.Functions.Protocol.Actors.ActorId do } end - field(:name, 1, type: :string) - field(:system, 2, type: :string) - field(:parent, 3, type: :string) + field :name, 1, type: :string + field :system, 2, type: :string + field :parent, 3, type: :string end defmodule Eigr.Functions.Protocol.Actors.Actor do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1200,15 +1195,14 @@ defmodule Eigr.Functions.Protocol.Actors.Actor do } end - field(:id, 1, type: Eigr.Functions.Protocol.Actors.ActorId) - field(:state, 2, type: Eigr.Functions.Protocol.Actors.ActorState) - field(:metadata, 6, type: Eigr.Functions.Protocol.Actors.Metadata) - field(:settings, 3, type: Eigr.Functions.Protocol.Actors.ActorSettings) - field(:actions, 4, repeated: true, type: Eigr.Functions.Protocol.Actors.Action) + field :id, 1, type: Eigr.Functions.Protocol.Actors.ActorId + field :state, 2, type: Eigr.Functions.Protocol.Actors.ActorState + field :metadata, 6, type: Eigr.Functions.Protocol.Actors.Metadata + field :settings, 3, type: Eigr.Functions.Protocol.Actors.ActorSettings + field :actions, 4, repeated: true, type: Eigr.Functions.Protocol.Actors.Action - field(:timer_actions, 5, + field :timer_actions, 5, repeated: true, type: Eigr.Functions.Protocol.Actors.FixedTimerAction, json_name: "timerActions" - ) -end +end \ No newline at end of file diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex index 2f02de63..5e96b9b6 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex @@ -1,10 +1,9 @@ defmodule Eigr.Functions.Protocol.Actors.PbExtension do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 - extend(Google.Protobuf.FieldOptions, :actor_id, 9999, + extend Google.Protobuf.FieldOptions, :actor_id, 9999, optional: true, type: :bool, json_name: "actorId" - ) -end +end \ No newline at end of file diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex index d95c85a5..213388f2 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex @@ -1,6 +1,6 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.Status do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -62,14 +62,14 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.Status do } end - field(:status, 1, type: :string) - field(:details, 2, type: :string) - field(:updated_at, 3, type: Google.Protobuf.Timestamp, json_name: "updatedAt") + field :status, 1, type: :string + field :details, 2, type: :string + field :updated_at, 3, type: Google.Protobuf.Timestamp, json_name: "updatedAt" end defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckReply do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -103,14 +103,15 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckReply do } end - field(:status, 1, type: Eigr.Functions.Protocol.Actors.Healthcheck.Status) + field :status, 1, type: Eigr.Functions.Protocol.Actors.Healthcheck.Status end defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service do @moduledoc false + use GRPC.Service, name: "eigr.functions.protocol.actors.healthcheck.HealthCheckActor", - protoc_gen_elixir_version: "0.12.0" + protoc_gen_elixir_version: "0.13.0" def descriptor do # credo:disable-for-next-line @@ -221,7 +222,6 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service do options: %Google.Protobuf.MethodOptions{ deprecated: false, idempotency_level: :IDEMPOTENCY_UNKNOWN, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{ {Google.Api.PbExtension, :http} => %Google.Api.HttpRule{ @@ -246,7 +246,6 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service do options: %Google.Protobuf.MethodOptions{ deprecated: false, idempotency_level: :IDEMPOTENCY_UNKNOWN, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{ {Google.Api.PbExtension, :http} => %Google.Api.HttpRule{ @@ -288,9 +287,9 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service do swift_prefix: nil, php_class_prefix: nil, php_namespace: nil, + php_generic_services: false, php_metadata_namespace: nil, ruby_package: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -690,3 +689,9 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service do } ) end + +defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Stub do + @moduledoc false + + use GRPC.Stub, service: Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service +end \ No newline at end of file diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex index 7bc475d8..7a3c939c 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex @@ -1,6 +1,6 @@ defmodule Eigr.Functions.Protocol.Status do @moduledoc false - use Protobuf, enum: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, enum: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -39,15 +39,15 @@ defmodule Eigr.Functions.Protocol.Status do } end - field(:UNKNOWN, 0) - field(:OK, 1) - field(:ACTOR_NOT_FOUND, 2) - field(:ERROR, 3) + field :UNKNOWN, 0 + field :OK, 1 + field :ACTOR_NOT_FOUND, 2 + field :ERROR, 3 end defmodule Eigr.Functions.Protocol.Context.MetadataEntry do @moduledoc false - use Protobuf, map: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, map: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -93,7 +93,6 @@ defmodule Eigr.Functions.Protocol.Context.MetadataEntry do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -105,13 +104,13 @@ defmodule Eigr.Functions.Protocol.Context.MetadataEntry do } end - field(:key, 1, type: :string) - field(:value, 2, type: :string) + field :key, 1, type: :string + field :value, 2, type: :string end defmodule Eigr.Functions.Protocol.Context.TagsEntry do @moduledoc false - use Protobuf, map: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, map: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -157,7 +156,6 @@ defmodule Eigr.Functions.Protocol.Context.TagsEntry do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -169,13 +167,13 @@ defmodule Eigr.Functions.Protocol.Context.TagsEntry do } end - field(:key, 1, type: :string) - field(:value, 2, type: :string) + field :key, 1, type: :string + field :value, 2, type: :string end defmodule Eigr.Functions.Protocol.Context do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -296,7 +294,6 @@ defmodule Eigr.Functions.Protocol.Context do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -348,7 +345,6 @@ defmodule Eigr.Functions.Protocol.Context do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -370,22 +366,21 @@ defmodule Eigr.Functions.Protocol.Context do } end - field(:state, 1, type: Google.Protobuf.Any) + field :state, 1, type: Google.Protobuf.Any - field(:metadata, 4, + field :metadata, 4, repeated: true, type: Eigr.Functions.Protocol.Context.MetadataEntry, map: true - ) - field(:tags, 5, repeated: true, type: Eigr.Functions.Protocol.Context.TagsEntry, map: true) - field(:caller, 2, type: Eigr.Functions.Protocol.Actors.ActorId) - field(:self, 3, type: Eigr.Functions.Protocol.Actors.ActorId) + field :tags, 5, repeated: true, type: Eigr.Functions.Protocol.Context.TagsEntry, map: true + field :caller, 2, type: Eigr.Functions.Protocol.Actors.ActorId + field :self, 3, type: Eigr.Functions.Protocol.Actors.ActorId end defmodule Eigr.Functions.Protocol.Noop do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -407,7 +402,7 @@ end defmodule Eigr.Functions.Protocol.JSONType do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -441,12 +436,12 @@ defmodule Eigr.Functions.Protocol.JSONType do } end - field(:content, 1, type: :string) + field :content, 1, type: :string end defmodule Eigr.Functions.Protocol.RegistrationRequest do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -494,17 +489,16 @@ defmodule Eigr.Functions.Protocol.RegistrationRequest do } end - field(:service_info, 1, type: Eigr.Functions.Protocol.ServiceInfo, json_name: "serviceInfo") + field :service_info, 1, type: Eigr.Functions.Protocol.ServiceInfo, json_name: "serviceInfo" - field(:actor_system, 2, + field :actor_system, 2, type: Eigr.Functions.Protocol.Actors.ActorSystem, json_name: "actorSystem" - ) end defmodule Eigr.Functions.Protocol.RegistrationResponse do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -552,13 +546,13 @@ defmodule Eigr.Functions.Protocol.RegistrationResponse do } end - field(:status, 1, type: Eigr.Functions.Protocol.RequestStatus) - field(:proxy_info, 2, type: Eigr.Functions.Protocol.ProxyInfo, json_name: "proxyInfo") + field :status, 1, type: Eigr.Functions.Protocol.RequestStatus + field :proxy_info, 2, type: Eigr.Functions.Protocol.ProxyInfo, json_name: "proxyInfo" end defmodule Eigr.Functions.Protocol.ServiceInfo do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -676,18 +670,18 @@ defmodule Eigr.Functions.Protocol.ServiceInfo do } end - field(:service_name, 1, type: :string, json_name: "serviceName") - field(:service_version, 2, type: :string, json_name: "serviceVersion") - field(:service_runtime, 3, type: :string, json_name: "serviceRuntime") - field(:support_library_name, 4, type: :string, json_name: "supportLibraryName") - field(:support_library_version, 5, type: :string, json_name: "supportLibraryVersion") - field(:protocol_major_version, 6, type: :int32, json_name: "protocolMajorVersion") - field(:protocol_minor_version, 7, type: :int32, json_name: "protocolMinorVersion") + field :service_name, 1, type: :string, json_name: "serviceName" + field :service_version, 2, type: :string, json_name: "serviceVersion" + field :service_runtime, 3, type: :string, json_name: "serviceRuntime" + field :support_library_name, 4, type: :string, json_name: "supportLibraryName" + field :support_library_version, 5, type: :string, json_name: "supportLibraryVersion" + field :protocol_major_version, 6, type: :int32, json_name: "protocolMajorVersion" + field :protocol_minor_version, 7, type: :int32, json_name: "protocolMinorVersion" end defmodule Eigr.Functions.Protocol.SpawnRequest do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -721,12 +715,12 @@ defmodule Eigr.Functions.Protocol.SpawnRequest do } end - field(:actors, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.ActorId) + field :actors, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.ActorId end defmodule Eigr.Functions.Protocol.SpawnResponse do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -760,12 +754,12 @@ defmodule Eigr.Functions.Protocol.SpawnResponse do } end - field(:status, 1, type: Eigr.Functions.Protocol.RequestStatus) + field :status, 1, type: Eigr.Functions.Protocol.RequestStatus end defmodule Eigr.Functions.Protocol.ProxyInfo do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -841,15 +835,15 @@ defmodule Eigr.Functions.Protocol.ProxyInfo do } end - field(:protocol_major_version, 1, type: :int32, json_name: "protocolMajorVersion") - field(:protocol_minor_version, 2, type: :int32, json_name: "protocolMinorVersion") - field(:proxy_name, 3, type: :string, json_name: "proxyName") - field(:proxy_version, 4, type: :string, json_name: "proxyVersion") + field :protocol_major_version, 1, type: :int32, json_name: "protocolMajorVersion" + field :protocol_minor_version, 2, type: :int32, json_name: "protocolMinorVersion" + field :proxy_name, 3, type: :string, json_name: "proxyName" + field :proxy_version, 4, type: :string, json_name: "proxyVersion" end defmodule Eigr.Functions.Protocol.SideEffect do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -883,12 +877,12 @@ defmodule Eigr.Functions.Protocol.SideEffect do } end - field(:request, 1, type: Eigr.Functions.Protocol.InvocationRequest) + field :request, 1, type: Eigr.Functions.Protocol.InvocationRequest end defmodule Eigr.Functions.Protocol.Broadcast do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -956,16 +950,16 @@ defmodule Eigr.Functions.Protocol.Broadcast do } end - oneof(:payload, 0) + oneof :payload, 0 - field(:channel_group, 1, type: :string, json_name: "channelGroup") - field(:value, 3, type: Google.Protobuf.Any, oneof: 0) - field(:noop, 4, type: Eigr.Functions.Protocol.Noop, oneof: 0) + field :channel_group, 1, type: :string, json_name: "channelGroup" + field :value, 3, type: Google.Protobuf.Any, oneof: 0 + field :noop, 4, type: Eigr.Functions.Protocol.Noop, oneof: 0 end defmodule Eigr.Functions.Protocol.Pipe do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1013,13 +1007,13 @@ defmodule Eigr.Functions.Protocol.Pipe do } end - field(:actor, 1, type: :string) - field(:action_name, 2, type: :string, json_name: "actionName") + field :actor, 1, type: :string + field :action_name, 2, type: :string, json_name: "actionName" end defmodule Eigr.Functions.Protocol.Forward do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1067,13 +1061,13 @@ defmodule Eigr.Functions.Protocol.Forward do } end - field(:actor, 1, type: :string) - field(:action_name, 2, type: :string, json_name: "actionName") + field :actor, 1, type: :string + field :action_name, 2, type: :string, json_name: "actionName" end defmodule Eigr.Functions.Protocol.Workflow do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1155,17 +1149,17 @@ defmodule Eigr.Functions.Protocol.Workflow do } end - oneof(:routing, 0) + oneof :routing, 0 - field(:broadcast, 2, type: Eigr.Functions.Protocol.Broadcast) - field(:effects, 1, repeated: true, type: Eigr.Functions.Protocol.SideEffect) - field(:pipe, 3, type: Eigr.Functions.Protocol.Pipe, oneof: 0) - field(:forward, 4, type: Eigr.Functions.Protocol.Forward, oneof: 0) + field :broadcast, 2, type: Eigr.Functions.Protocol.Broadcast + field :effects, 1, repeated: true, type: Eigr.Functions.Protocol.SideEffect + field :pipe, 3, type: Eigr.Functions.Protocol.Pipe, oneof: 0 + field :forward, 4, type: Eigr.Functions.Protocol.Forward, oneof: 0 end defmodule Eigr.Functions.Protocol.InvocationRequest.MetadataEntry do @moduledoc false - use Protobuf, map: true, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, map: true, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1211,7 +1205,6 @@ defmodule Eigr.Functions.Protocol.InvocationRequest.MetadataEntry do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -1223,13 +1216,13 @@ defmodule Eigr.Functions.Protocol.InvocationRequest.MetadataEntry do } end - field(:key, 1, type: :string) - field(:value, 2, type: :string) + field :key, 1, type: :string + field :value, 2, type: :string end defmodule Eigr.Functions.Protocol.InvocationRequest do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1434,7 +1427,6 @@ defmodule Eigr.Functions.Protocol.InvocationRequest do deprecated: false, map_entry: true, deprecated_legacy_json_field_conflicts: nil, - # features: nil, uninterpreted_option: [], __pb_extensions__: %{}, __unknown_fields__: [] @@ -1462,30 +1454,29 @@ defmodule Eigr.Functions.Protocol.InvocationRequest do } end - oneof(:payload, 0) + oneof :payload, 0 - field(:system, 1, type: Eigr.Functions.Protocol.Actors.ActorSystem) - field(:actor, 2, type: Eigr.Functions.Protocol.Actors.Actor) - field(:action_name, 3, type: :string, json_name: "actionName") - field(:value, 4, type: Google.Protobuf.Any, oneof: 0) - field(:noop, 7, type: Eigr.Functions.Protocol.Noop, oneof: 0) - field(:async, 5, type: :bool) - field(:caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId) + field :system, 1, type: Eigr.Functions.Protocol.Actors.ActorSystem + field :actor, 2, type: Eigr.Functions.Protocol.Actors.Actor + field :action_name, 3, type: :string, json_name: "actionName" + field :value, 4, type: Google.Protobuf.Any, oneof: 0 + field :noop, 7, type: Eigr.Functions.Protocol.Noop, oneof: 0 + field :async, 5, type: :bool + field :caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId - field(:metadata, 8, + field :metadata, 8, repeated: true, type: Eigr.Functions.Protocol.InvocationRequest.MetadataEntry, map: true - ) - field(:scheduled_to, 9, type: :int64, json_name: "scheduledTo") - field(:pooled, 10, type: :bool) - field(:register_ref, 11, type: :string, json_name: "registerRef") + field :scheduled_to, 9, type: :int64, json_name: "scheduledTo" + field :pooled, 10, type: :bool + field :register_ref, 11, type: :string, json_name: "registerRef" end defmodule Eigr.Functions.Protocol.ActorInvocation do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1595,19 +1586,19 @@ defmodule Eigr.Functions.Protocol.ActorInvocation do } end - oneof(:payload, 0) + oneof :payload, 0 - field(:actor, 1, type: Eigr.Functions.Protocol.Actors.ActorId) - field(:action_name, 2, type: :string, json_name: "actionName") - field(:current_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "currentContext") - field(:value, 4, type: Google.Protobuf.Any, oneof: 0) - field(:noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0) - field(:caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId) + field :actor, 1, type: Eigr.Functions.Protocol.Actors.ActorId + field :action_name, 2, type: :string, json_name: "actionName" + field :current_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "currentContext" + field :value, 4, type: Google.Protobuf.Any, oneof: 0 + field :noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0 + field :caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId end defmodule Eigr.Functions.Protocol.ActorInvocationResponse do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1731,20 +1722,20 @@ defmodule Eigr.Functions.Protocol.ActorInvocationResponse do } end - oneof(:payload, 0) + oneof :payload, 0 - field(:actor_name, 1, type: :string, json_name: "actorName") - field(:actor_system, 2, type: :string, json_name: "actorSystem") - field(:updated_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "updatedContext") - field(:value, 4, type: Google.Protobuf.Any, oneof: 0) - field(:noop, 6, type: Eigr.Functions.Protocol.Noop, oneof: 0) - field(:workflow, 5, type: Eigr.Functions.Protocol.Workflow) - field(:checkpoint, 7, type: :bool) + field :actor_name, 1, type: :string, json_name: "actorName" + field :actor_system, 2, type: :string, json_name: "actorSystem" + field :updated_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "updatedContext" + field :value, 4, type: Google.Protobuf.Any, oneof: 0 + field :noop, 6, type: Eigr.Functions.Protocol.Noop, oneof: 0 + field :workflow, 5, type: Eigr.Functions.Protocol.Workflow + field :checkpoint, 7, type: :bool end defmodule Eigr.Functions.Protocol.InvocationResponse do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1840,18 +1831,18 @@ defmodule Eigr.Functions.Protocol.InvocationResponse do } end - oneof(:payload, 0) + oneof :payload, 0 - field(:status, 1, type: Eigr.Functions.Protocol.RequestStatus) - field(:system, 2, type: Eigr.Functions.Protocol.Actors.ActorSystem) - field(:actor, 3, type: Eigr.Functions.Protocol.Actors.Actor) - field(:value, 4, type: Google.Protobuf.Any, oneof: 0) - field(:noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0) + field :status, 1, type: Eigr.Functions.Protocol.RequestStatus + field :system, 2, type: Eigr.Functions.Protocol.Actors.ActorSystem + field :actor, 3, type: Eigr.Functions.Protocol.Actors.Actor + field :value, 4, type: Google.Protobuf.Any, oneof: 0 + field :noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0 end defmodule Eigr.Functions.Protocol.RequestStatus do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -1899,6 +1890,6 @@ defmodule Eigr.Functions.Protocol.RequestStatus do } end - field(:status, 1, type: Eigr.Functions.Protocol.Status, enum: true) - field(:message, 2, type: :string) -end + field :status, 1, type: Eigr.Functions.Protocol.Status, enum: true + field :message, 2, type: :string +end \ No newline at end of file diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex index 1b3b9b94..7a57ec71 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex @@ -1,6 +1,6 @@ defmodule Eigr.Functions.Protocol.State.Revision do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -34,12 +34,12 @@ defmodule Eigr.Functions.Protocol.State.Revision do } end - field(:value, 1, type: :int64) + field :value, 1, type: :int64 end defmodule Eigr.Functions.Protocol.State.Checkpoint do @moduledoc false - use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3 + use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 def descriptor do # credo:disable-for-next-line @@ -87,6 +87,6 @@ defmodule Eigr.Functions.Protocol.State.Checkpoint do } end - field(:revision, 1, type: Eigr.Functions.Protocol.State.Revision) - field(:state, 2, type: Eigr.Functions.Protocol.Actors.ActorState) -end + field :revision, 1, type: Eigr.Functions.Protocol.State.Revision + field :state, 2, type: Eigr.Functions.Protocol.Actors.ActorState +end \ No newline at end of file diff --git a/mix.lock b/mix.lock index 354676ff..b8c17330 100644 --- a/mix.lock +++ b/mix.lock @@ -27,6 +27,8 @@ "exqlite": {:hex, :exqlite, "0.19.0", "0f3ee29e35bed38552dd0ed59600aa81c78f867f5b5ff0e17d330148e0465483", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "55a8fbb0443f03d4a256e3458bd1203eff5037a6624b76460eaaa9080f462b06"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, + "flame": {:hex, :flame, "0.5.1", "339130ed9dff761efc1b2c001839e6d16aa9af291a1e155d8c14fa9b42c03caa", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, ">= 0.0.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "b09ac62b187f40fa7f959d6faca58aae0e575ff21435a8afd79727b8e5631085"}, + "flame_k8s_backend": {:hex, :flame_k8s_backend, "0.5.4", "4a14e5dd40ae5d26c47407e15acf81e322835fbbfb9e4b9c9e200ac5bf2cfaa8", [:mix], [{:flame, "~> 0.4.0 or ~> 0.5.0", [hex: :flame, repo: "hexpm", optional: false]}], "hexpm", "2a7973223e49d869d032e732425ae67283fa779d9c5e2f759d7f113473b86c42"}, "flow": {:hex, :flow, "1.2.4", "1dd58918287eb286656008777cb32714b5123d3855956f29aa141ebae456922d", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "874adde96368e71870f3510b91e35bc31652291858c86c0e75359cbdd35eb211"}, "gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"}, "gnat": {:hex, :gnat, "1.8.5", "31d7f75dcca90164b2d811bcbc1a94b9049a0f586c219594687d6bd9493043a5", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:cowlib, "~> 2.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:nkeys, "~> 0.2", [hex: :nkeys, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5e62a8f6f02a12191a9ca79ea94f5899db7ec32a0e8554cac9930196298e8cb6"}, diff --git a/spawn_proxy/proxy/mix.exs b/spawn_proxy/proxy/mix.exs index fa80adf7..9f5bd275 100644 --- a/spawn_proxy/proxy/mix.exs +++ b/spawn_proxy/proxy/mix.exs @@ -38,6 +38,7 @@ defmodule Proxy.MixProject do path: "../../spawn_statestores/statestores_native", optional: false}, {:bakeware, "~> 0.2"}, {:bandit, "~> 1.5"}, + {:flame_k8s_backend, "~> 0.5.4"}, {:observer_cli, "~> 1.7"}, {:sobelow, "~> 0.13", only: [:dev, :test], runtime: false} ] From 0b8d8545bc99fa76fb381d13d253c98980431dca Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sat, 28 Sep 2024 15:51:59 -0300 Subject: [PATCH 04/34] Added topology and node selector --- examples/topology/host.yaml | 48 ++++-- .../spawn_operator/k8s/proxy/deployment.ex | 62 +++++++- spawn_operator/spawn_operator/mix.lock | 2 + .../resources/actorhost/deployment_test.exs | 150 ++++++++++++++++++ .../spawn_operator/test/support/factory.ex | 24 +++ 5 files changed, 269 insertions(+), 17 deletions(-) diff --git a/examples/topology/host.yaml b/examples/topology/host.yaml index 8d1a08f6..2fe3b6a1 100644 --- a/examples/topology/host.yaml +++ b/examples/topology/host.yaml @@ -8,24 +8,50 @@ metadata: # Mandatory. Name of the ActorSystem declared in ActorSystem CRD spawn-eigr.io/actor-system: spawn-system spec: + topology: + # affinity: + # podAffinity: + # preferredDuringSchedulingIgnoredDuringExecution: + # - weight: 50 + # podAffinityTerm: + # labelSelector: + # matchExpressions: + # - key: actor-system + # operator: In + # values: + # - system + # topologyKey: kubernetes.io/hostname + + # podAntiAffinity: + # preferredDuringSchedulingIgnoredDuringExecution: + # - weight: 100 + # podAffinityTerm: + # labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - app_name + # topologyKey: kubernetes.io/hostname + nodeSelector: + gpu: "false" + tolerations: + - key: "cpu-machines" + operator: "Exists" + effect: "NoExecute" host: image: eigr/spawn-springboot-examples:0.5.5 # Mandatory - topology: - nodeSelector: - gpu: "false" - tolerations: - - key: "cpu-machines" - operator: "Exists" - effect: "NoExecute" - # this configure podTemplate for Task Actors - taskActors: - - parentName: Jose + # this configure podTemplate for Task Actors + taskActors: + - parentName: Jose + topology: nodeSelector: gpu: "true" tolerations: - key: "gpu-machines" operator: "Exists" effect: "NoExecute" - - parentName: Franchesco + - parentName: Franchesco + topology: nodeSelector: beam: "true" diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index e9c342b5..c2cca071 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -70,6 +70,9 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do } = _resource ) do host_params = Map.get(params, "host") + task_actors_config = Map.get(host_params, "taskActors", %{}) + topology = Map.get(params, "topology", %{}) + replicas = max(1, Map.get(params, "replicas", @default_actor_host_function_replicas)) embedded = Map.get(host_params, "embedded", false) @@ -109,8 +112,16 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do }, "spec" => %{ - "affinity" => Map.get(host_params, "affinity", build_affinity(system, name)), - "containers" => get_containers(embedded, system, name, host_params, annotations), + "affinity" => Map.get(topology, "affinity", build_affinity(system, name)), + "containers" => + get_containers( + embedded, + system, + name, + host_params, + annotations, + task_actors_config + ), "initContainers" => [ %{ "name" => "init-certificates", @@ -131,6 +142,8 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do ], "serviceAccountName" => "#{system}-sa" } + |> maybe_put_node_selector(topology) + |> maybe_put_node_tolerations(topology) |> maybe_put_volumes(params) |> maybe_set_termination_period(params) } @@ -185,10 +198,28 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do } end - defp get_containers(true, system, name, host_params, annotations) do + defp build_task_env(task_actors_config) do + value = + task_actors_config + |> Jason.encode!() + |> Base.encode32() + + [ + %{"name" => "SPAWN_PROXY_TASK_CONFIG", "value" => value} + ] + end + + defp get_containers(true, system, name, host_params, annotations, task_actors_config) do actor_host_function_image = Map.get(host_params, "image") - actor_host_function_envs = Map.get(host_params, "env", []) ++ @default_actor_host_function_env + actor_host_function_envs = + if length(Map.values(task_actors_config)) == 0 do + Map.get(host_params, "env", []) ++ @default_actor_host_function_env + else + Map.get(host_params, "env", []) ++ + @default_actor_host_function_env ++ + build_task_env(task_actors_config) + end proxy_http_port = String.to_integer(annotations.proxy_http_port) @@ -230,7 +261,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do ] end - defp get_containers(false, system, name, host_params, annotations) do + defp get_containers(false, system, name, host_params, annotations, task_actors_config) do actor_host_function_image = Map.get(host_params, "image") actor_host_function_envs = @@ -247,12 +278,19 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do %{"containerPort" => proxy_http_port, "name" => "proxy-http"} ] + envs = + if length(Map.values(task_actors_config)) == 0 do + @default_actor_host_function_env + else + @default_actor_host_function_env ++ build_task_env(task_actors_config) + end + proxy_container = %{ "name" => "sidecar", "image" => "#{annotations.proxy_image_tag}", "imagePullPolicy" => "Always", - "env" => @default_actor_host_function_env, + "env" => envs, "ports" => proxy_actor_host_function_ports, "livenessProbe" => %{ "httpGet" => %{ @@ -310,6 +348,18 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do ] end + defp maybe_put_node_selector(spec, %{"nodeSelector" => selectors} = _topology) do + Map.merge(spec, %{"nodeSelector" => selectors}) + end + + defp maybe_put_node_selector(spec, _), do: spec + + defp maybe_put_node_tolerations(spec, %{"tolerations" => tolerations} = _topology) do + Map.merge(spec, %{"tolerations" => tolerations}) + end + + defp maybe_put_node_tolerations(spec, _), do: spec + defp maybe_put_ports_to_host_container(spec, %{"ports" => ports}) do Map.put(spec, "ports", ports) end diff --git a/spawn_operator/spawn_operator/mix.lock b/spawn_operator/spawn_operator/mix.lock index 21e31005..cb1e4ae1 100644 --- a/spawn_operator/spawn_operator/mix.lock +++ b/spawn_operator/spawn_operator/mix.lock @@ -56,7 +56,9 @@ "nkeys": {:hex, :nkeys, "0.2.2", "b1ab3324ed4f3a2c9658d7e80feeef86b4d15fbfd12ca5c8cf068289f582fcfa", [:mix], [{:ed25519, "~> 1.3", [hex: :ed25519, repo: "hexpm", optional: false]}], "hexpm", "3578802427b8d1d11ea6dd785c2ab774f527e2c3e449e67bd34612ab71ca471d"}, "opentelemetry": {:hex, :opentelemetry, "1.4.0", "f928923ed80adb5eb7894bac22e9a198478e6a8f04020ae1d6f289fdcad0b498", [:rebar3], [{:opentelemetry_api, "~> 1.3.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "50b32ce127413e5d87b092b4d210a3449ea80cd8224090fe68d73d576a3faa15"}, "opentelemetry_api": {:hex, :opentelemetry_api, "1.3.0", "03e2177f28dd8d11aaa88e8522c81c2f6a788170fe52f7a65262340961e663f9", [:mix, :rebar3], [{:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "b9e5ff775fd064fa098dba3c398490b77649a352b40b0b730a6b7dc0bdd68858"}, + "opentelemetry_ecto": {:hex, :opentelemetry_ecto, "1.2.0", "2382cb47ddc231f953d3b8263ed029d87fbf217915a1da82f49159d122b64865", [:mix], [{:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "70dfa2e79932e86f209df00e36c980b17a32f82d175f0068bf7ef9a96cf080cf"}, "opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.7.0", "dec4e90c0667cf11a3642f7fe71982dbc0c6bfbb8725a0b13766830718cf0d98", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.4.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.3.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.18", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "d0f25f6439ec43f2561537c3fabbe177b38547cddaa3a692cbb8f4770dbefc1e"}, + "opentelemetry_process_propagator": {:hex, :opentelemetry_process_propagator, "0.3.0", "ef5b2059403a1e2b2d2c65914e6962e56371570b8c3ab5323d7a8d3444fb7f84", [:mix, :rebar3], [{:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "7243cb6de1523c473cba5b1aefa3f85e1ff8cc75d08f367104c1e11919c8c029"}, "opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "0.2.0", "b67fe459c2938fcab341cb0951c44860c62347c005ace1b50f8402576f241435", [:mix, :rebar3], [], "hexpm", "d61fa1f5639ee8668d74b527e6806e0503efc55a42db7b5f39939d84c07d6895"}, "owl": {:hex, :owl, "0.8.0", "0ef925cb784311093d4e3734822960cbdbdb13b095d748bb5bc82abcd5b56732", [:mix], [], "hexpm", "0a5586ceb1a12f4bbda90e330c20e6ea034552335d09466c10e4218c98977529"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, diff --git a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs index 8b3b7ad5..f8641ad8 100644 --- a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs +++ b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs @@ -11,6 +11,7 @@ defmodule DeploymentTest do simple_host_with_ports = build_simple_actor_host_with_ports() simple_actor_host_with_volume_mounts = build_simple_actor_host_with_volume_mounts() embedded_actor_host = build_embedded_actor_host() + embedded_actor_host_with_node_selector = build_embedded_actor_host_with_node_selector() embedded_actor_host_with_volume_mounts = build_embedded_actor_host_with_volume_mounts() %{ @@ -18,6 +19,7 @@ defmodule DeploymentTest do simple_host_with_ports: simple_host_with_ports, simple_actor_host_with_volume_mounts: simple_actor_host_with_volume_mounts, embedded_actor_host: embedded_actor_host, + embedded_actor_host_with_node_selector: embedded_actor_host_with_node_selector, embedded_actor_host_with_volume_mounts: embedded_actor_host_with_volume_mounts } end @@ -170,6 +172,154 @@ defmodule DeploymentTest do } == build_host_deploy(embedded_actor_host) end + test "generate embedded deployment with defaults and node selector", ctx do + %{ + embedded_actor_host_with_node_selector: embedded_actor_host_with_node_selector + } = ctx + + assert %{ + "apiVersion" => "apps/v1", + "kind" => "Deployment", + "metadata" => %{ + "labels" => %{"actor-system" => "spawn-system", "app" => "spawn-test"}, + "name" => "spawn-test", + "namespace" => "default" + }, + "spec" => %{ + "replicas" => 1, + "selector" => %{ + "matchLabels" => %{"actor-system" => "spawn-system", "app" => "spawn-test"} + }, + "strategy" => %{ + "rollingUpdate" => %{"maxSurge" => "50%", "maxUnavailable" => 0}, + "type" => "RollingUpdate" + }, + "template" => %{ + "metadata" => %{ + "annotations" => %{ + "prometheus.io/path" => "/metrics", + "prometheus.io/port" => "9001", + "prometheus.io/scrape" => "true" + }, + "labels" => %{"actor-system" => "spawn-system", "app" => "spawn-test"} + }, + "spec" => %{ + "affinity" => %{ + "podAffinity" => %{ + "preferredDuringSchedulingIgnoredDuringExecution" => [ + %{ + "weight" => 50, + "podAffinityTerm" => %{ + "labelSelector" => %{ + "matchExpressions" => [ + %{ + "key" => "actor-system", + "operator" => "In", + "values" => [ + "spawn-system" + ] + } + ] + }, + "topologyKey" => "kubernetes.io/hostname" + } + } + ] + }, + "podAntiAffinity" => %{ + "preferredDuringSchedulingIgnoredDuringExecution" => [ + %{ + "weight" => 100, + "podAffinityTerm" => %{ + "labelSelector" => %{ + "matchExpressions" => [ + %{ + "key" => "app", + "operator" => "In", + "values" => [ + "spawn-test" + ] + } + ] + }, + "topologyKey" => "kubernetes.io/hostname" + } + } + ] + } + }, + "containers" => [ + %{ + "env" => [ + %{"name" => "RELEASE_NAME", "value" => "spawn"}, + %{ + "name" => "NAMESPACE", + "valueFrom" => %{ + "fieldRef" => %{"fieldPath" => "metadata.namespace"} + } + }, + %{ + "name" => "POD_IP", + "valueFrom" => %{"fieldRef" => %{"fieldPath" => "status.podIP"}} + }, + %{"name" => "SPAWN_PROXY_PORT", "value" => "9001"}, + %{"name" => "SPAWN_PROXY_INTERFACE", "value" => "0.0.0.0"}, + %{"name" => "RELEASE_DISTRIBUTION", "value" => "name"}, + %{"name" => "RELEASE_NODE", "value" => "$(RELEASE_NAME)@$(POD_IP)"} + ], + "envFrom" => [ + %{"configMapRef" => %{"name" => "spawn-test-sidecar-cm"}}, + %{"secretRef" => %{"name" => "spawn-system-secret"}} + ], + "image" => "eigr/spawn-test:latest", + "name" => "actorhost", + "ports" => [ + %{"containerPort" => 4369, "name" => "epmd"}, + %{"containerPort" => 9001, "name" => "proxy-http"} + ], + "resources" => %{ + "requests" => %{ + "cpu" => "100m", + "ephemeral-storage" => "1M", + "memory" => "80Mi" + } + }, + "volumeMounts" => [%{"mountPath" => "/app/certs", "name" => "certs"}] + } + ], + "terminationGracePeriodSeconds" => 405, + "initContainers" => [ + %{ + "args" => [ + "--environment", + :prod, + "--secret", + "tls-certs", + "--namespace", + "default", + "--service", + "spawn-system", + "--to", + "default" + ], + "image" => "ghcr.io/eigr/spawn-initializer:1.4.3", + "name" => "init-certificates" + } + ], + "serviceAccountName" => "spawn-system-sa", + "volumes" => [ + %{ + "name" => "certs", + "secret" => %{"optional" => true, "secretName" => "tls-certs"} + } + ], + "nodeSelector" => %{"gpu" => "false"} + } + } + } + } == build_host_deploy(embedded_actor_host_with_node_selector) + end + test "generate embedded deployment with volumeMount", ctx do %{ embedded_actor_host_with_volume_mounts: embedded_actor_host_with_volume_mounts diff --git a/spawn_operator/spawn_operator/test/support/factory.ex b/spawn_operator/spawn_operator/test/support/factory.ex index 221f9cb4..ece0423e 100644 --- a/spawn_operator/spawn_operator/test/support/factory.ex +++ b/spawn_operator/spawn_operator/test/support/factory.ex @@ -20,6 +20,30 @@ defmodule SpawnOperator.FactoryTest do } end + def build_embedded_actor_host_with_node_selector(attrs \\ []) do + %{ + "apiVersion" => "spawn-eigr.io/v1", + "kind" => "ActorHost", + "metadata" => %{ + "name" => attrs[:name] || "spawn-test", + "system" => "spawn-system", + "namespace" => "default", + "generation" => 1 + }, + "spec" => %{ + "topology" => %{ + "nodeSelector" => %{ + "gpu" => "false" + } + }, + "host" => %{ + "embedded" => true, + "image" => attrs[:host_image] || "eigr/spawn-test:latest" + } + } + } + end + def build_embedded_actor_host_with_volume_mounts(attrs \\ []) do %{ "apiVersion" => "spawn-eigr.io/v1", From 2187c1b25281136e314bf5f34bb7d07527e323d9 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sat, 28 Sep 2024 16:19:37 -0300 Subject: [PATCH 05/34] Add new test to validate SPAWN_PROXY_TASK_CONFIG env --- .../spawn_operator/k8s/proxy/deployment.ex | 6 +- .../resources/actorhost/deployment_test.exs | 152 ++++++++++++++++++ .../spawn_operator/test/support/factory.ex | 34 ++++ 3 files changed, 189 insertions(+), 3 deletions(-) diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index c2cca071..0a9c60ed 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -70,7 +70,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do } = _resource ) do host_params = Map.get(params, "host") - task_actors_config = Map.get(host_params, "taskActors", %{}) + task_actors_config = %{"taskActors" => Map.get(host_params, "taskActors", %{})} topology = Map.get(params, "topology", %{}) replicas = max(1, Map.get(params, "replicas", @default_actor_host_function_replicas)) @@ -213,7 +213,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do actor_host_function_image = Map.get(host_params, "image") actor_host_function_envs = - if length(Map.values(task_actors_config)) == 0 do + if is_nil(task_actors_config) || List.first(Map.values(task_actors_config)) == %{} do Map.get(host_params, "env", []) ++ @default_actor_host_function_env else Map.get(host_params, "env", []) ++ @@ -279,7 +279,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do ] envs = - if length(Map.values(task_actors_config)) == 0 do + if is_nil(task_actors_config) || List.first(Map.values(task_actors_config)) == %{} do @default_actor_host_function_env else @default_actor_host_function_env ++ build_task_env(task_actors_config) diff --git a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs index f8641ad8..8a64a545 100644 --- a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs +++ b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs @@ -11,7 +11,9 @@ defmodule DeploymentTest do simple_host_with_ports = build_simple_actor_host_with_ports() simple_actor_host_with_volume_mounts = build_simple_actor_host_with_volume_mounts() embedded_actor_host = build_embedded_actor_host() + embedded_actor_host_with_node_selector = build_embedded_actor_host_with_node_selector() + embedded_actor_host_with_task_actors = build_embedded_actor_host_with_task_actors() embedded_actor_host_with_volume_mounts = build_embedded_actor_host_with_volume_mounts() %{ @@ -20,6 +22,7 @@ defmodule DeploymentTest do simple_actor_host_with_volume_mounts: simple_actor_host_with_volume_mounts, embedded_actor_host: embedded_actor_host, embedded_actor_host_with_node_selector: embedded_actor_host_with_node_selector, + embedded_actor_host_with_task_actors: embedded_actor_host_with_task_actors, embedded_actor_host_with_volume_mounts: embedded_actor_host_with_volume_mounts } end @@ -320,6 +323,155 @@ defmodule DeploymentTest do } == build_host_deploy(embedded_actor_host_with_node_selector) end + test "generate embedded deployment with defaults and node selector and task actors", ctx do + %{ + embedded_actor_host_with_task_actors: embedded_actor_host_with_task_actors + } = ctx + + assert %{ + "apiVersion" => "apps/v1", + "kind" => "Deployment", + "metadata" => %{ + "labels" => %{"actor-system" => "spawn-system", "app" => "spawn-test"}, + "name" => "spawn-test", + "namespace" => "default" + }, + "spec" => %{ + "replicas" => 1, + "selector" => %{ + "matchLabels" => %{"actor-system" => "spawn-system", "app" => "spawn-test"} + }, + "strategy" => %{ + "rollingUpdate" => %{"maxSurge" => "50%", "maxUnavailable" => 0}, + "type" => "RollingUpdate" + }, + "template" => %{ + "metadata" => %{ + "annotations" => %{ + "prometheus.io/path" => "/metrics", + "prometheus.io/port" => "9001", + "prometheus.io/scrape" => "true" + }, + "labels" => %{"actor-system" => "spawn-system", "app" => "spawn-test"} + }, + "spec" => %{ + "affinity" => %{ + "podAffinity" => %{ + "preferredDuringSchedulingIgnoredDuringExecution" => [ + %{ + "weight" => 50, + "podAffinityTerm" => %{ + "labelSelector" => %{ + "matchExpressions" => [ + %{ + "key" => "actor-system", + "operator" => "In", + "values" => [ + "spawn-system" + ] + } + ] + }, + "topologyKey" => "kubernetes.io/hostname" + } + } + ] + }, + "podAntiAffinity" => %{ + "preferredDuringSchedulingIgnoredDuringExecution" => [ + %{ + "weight" => 100, + "podAffinityTerm" => %{ + "labelSelector" => %{ + "matchExpressions" => [ + %{ + "key" => "app", + "operator" => "In", + "values" => [ + "spawn-test" + ] + } + ] + }, + "topologyKey" => "kubernetes.io/hostname" + } + } + ] + } + }, + "containers" => [ + %{ + "env" => [ + %{"name" => "RELEASE_NAME", "value" => "spawn"}, + %{ + "name" => "NAMESPACE", + "valueFrom" => %{ + "fieldRef" => %{"fieldPath" => "metadata.namespace"} + } + }, + %{ + "name" => "POD_IP", + "valueFrom" => %{"fieldRef" => %{"fieldPath" => "status.podIP"}} + }, + %{"name" => "SPAWN_PROXY_PORT", "value" => "9001"}, + %{"name" => "SPAWN_PROXY_INTERFACE", "value" => "0.0.0.0"}, + %{"name" => "RELEASE_DISTRIBUTION", "value" => "name"}, + %{"name" => "RELEASE_NODE", "value" => "$(RELEASE_NAME)@$(POD_IP)"}, + %{"name" => "SPAWN_PROXY_TASK_CONFIG", "value" => "PMRHIYLTNNAWG5DPOJZSEOS3PMRHAYLSMVXHITTBNVSSEORCJJXXGZJCFQRHI33QN5WG6Z3ZEI5HWITON5SGKU3FNRSWG5DPOIRDU6ZCM5YHKIR2EJTGC3DTMURH27L5LV6Q===="} + ], + "envFrom" => [ + %{"configMapRef" => %{"name" => "spawn-test-sidecar-cm"}}, + %{"secretRef" => %{"name" => "spawn-system-secret"}} + ], + "image" => "eigr/spawn-test:latest", + "name" => "actorhost", + "ports" => [ + %{"containerPort" => 4369, "name" => "epmd"}, + %{"containerPort" => 9001, "name" => "proxy-http"} + ], + "resources" => %{ + "requests" => %{ + "cpu" => "100m", + "ephemeral-storage" => "1M", + "memory" => "80Mi" + } + }, + "volumeMounts" => [%{"mountPath" => "/app/certs", "name" => "certs"}] + } + ], + "terminationGracePeriodSeconds" => 405, + "initContainers" => [ + %{ + "args" => [ + "--environment", + :prod, + "--secret", + "tls-certs", + "--namespace", + "default", + "--service", + "spawn-system", + "--to", + "default" + ], + "image" => "ghcr.io/eigr/spawn-initializer:1.4.3", + "name" => "init-certificates" + } + ], + "serviceAccountName" => "spawn-system-sa", + "volumes" => [ + %{ + "name" => "certs", + "secret" => %{"optional" => true, "secretName" => "tls-certs"} + } + ], + "nodeSelector" => %{"gpu" => "false"} + } + } + } + } == build_host_deploy(embedded_actor_host_with_task_actors) + end + test "generate embedded deployment with volumeMount", ctx do %{ embedded_actor_host_with_volume_mounts: embedded_actor_host_with_volume_mounts diff --git a/spawn_operator/spawn_operator/test/support/factory.ex b/spawn_operator/spawn_operator/test/support/factory.ex index ece0423e..41f1c2fa 100644 --- a/spawn_operator/spawn_operator/test/support/factory.ex +++ b/spawn_operator/spawn_operator/test/support/factory.ex @@ -44,6 +44,40 @@ defmodule SpawnOperator.FactoryTest do } end + def build_embedded_actor_host_with_task_actors(attrs \\ []) do + %{ + "apiVersion" => "spawn-eigr.io/v1", + "kind" => "ActorHost", + "metadata" => %{ + "name" => attrs[:name] || "spawn-test", + "system" => "spawn-system", + "namespace" => "default", + "generation" => 1 + }, + "spec" => %{ + "topology" => %{ + "nodeSelector" => %{ + "gpu" => "false" + } + }, + "host" => %{ + "embedded" => true, + "image" => attrs[:host_image] || "eigr/spawn-test:latest", + "taskActors" => [ + %{ + "parentName" => "Jose", + "topology" => %{ + "nodeSelector" => %{ + "gpu" => "false" + } + } + } + ] + } + } + } + end + def build_embedded_actor_host_with_volume_mounts(attrs \\ []) do %{ "apiVersion" => "spawn-eigr.io/v1", From d016b4a7e52de94f2240987f53d89906292cbf7d Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 03:10:52 -0300 Subject: [PATCH 06/34] Invoke using flame --- Makefile | 4 +- examples/topology/host.yaml | 9 + lib/actors/actor/entity/entity.ex | 28 ++- lib/sidecar/grpc/dispatcher.ex | 1 - .../functions/protocol/actors/actor.pb.ex | 97 +++++----- .../protocol/actors/extensions.pb.ex | 5 +- .../protocol/actors/healthcheck.pb.ex | 10 +- .../functions/protocol/actors/protocol.pb.ex | 169 +++++++++--------- .../functions/protocol/actors/state.pb.ex | 8 +- lib/spawn/cluster/cluster_supervisor.ex | 15 +- lib/spawn/cluster/provisioner/scheduler.ex | 9 + .../cluster/provisioner_pool_supervisor.ex | 131 ++++++++++++++ lib/spawn/utils/common.ex | 4 + mix.exs | 1 + .../spawn_operator/k8s/proxy/deployment.ex | 23 +-- .../resources/actorhost/deployment_test.exs | 6 +- spawn_proxy/proxy/mix.exs | 1 - test/actors/actors_test.exs | 24 +++ test/support/factory.ex | 1 + 19 files changed, 385 insertions(+), 161 deletions(-) create mode 100644 lib/spawn/cluster/provisioner/scheduler.ex create mode 100644 lib/spawn/cluster/provisioner_pool_supervisor.ex diff --git a/Makefile b/Makefile index 3f85a43d..3cd4d230 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ build-all-images: #docker build --no-cache -f Dockerfile-elixir-example -t ${spawn-sdk-example-image} . test-spawn: - MIX_ENV=test PROXY_DATABASE_TYPE=mariadb PROXY_DATABASE_PORT=3307 PROXY_DATABASE_POOL_SIZE=15 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test + MIX_ENV=test SPAWN_PROXY_LOGGER_LEVEL=info SPAWN_PROXY_TASK_CONFIG="PMRHIYLTNNAWG5DPOJZSEOS3PMRHAYLSMVXHITTBNVSSEORCJJXXGZJCFQRHI33QN5WG6Z3ZEI5HWITON5SGKU3FNRSWG5DPOIRDU6ZCM5YHKIR2EJTGC3DTMURH27L5LV6Q====" PROXY_DATABASE_TYPE=native PROXY_DATABASE_PORT=3307 PROXY_DATABASE_POOL_SIZE=15 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test test-statestores_mysql: cd spawn_statestores/statestores_mysql && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test @@ -161,7 +161,7 @@ run-proxy-local2: ERL_ZFLAGS='-proto_dist inet_tls -ssl_dist_optfile rel/overlays/local-mtls.ssl.conf' cd spawn_proxy/proxy && mix deps.get && PROXY_DATABASE_TYPE=$(database) PROXY_HTTP_PORT=9003 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= iex --name spawn_a2@test.default.svc -S mix run-proxy-local-3: - cd spawn_proxy/proxy && mix deps.get && OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4317 OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc OTEL_EXPORTER_OTLP_TRACES_COMPRESSION=gzip SPAWN_PROXY_LOGGER_LEVEL=info PROXY_CLUSTER_STRATEGY=epmd SPAWN_USE_INTERNAL_NATS=false SPAWN_PUBSUB_ADAPTER=native PROXY_DATABASE_PORT=3307 PROXY_DATABASE_TYPE=native PROXY_DATABASE_POOL_SIZE=30 PROXY_HTTP_PORT=9001 USER_FUNCTION_PORT=8090 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= iex --name spawn_a3@127.0.0.1 -S mix + cd spawn_proxy/proxy && mix deps.get && OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4317 OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc OTEL_EXPORTER_OTLP_TRACES_COMPRESSION=gzip PROXY_CLUSTER_STRATEGY=epmd SPAWN_USE_INTERNAL_NATS=false SPAWN_PUBSUB_ADAPTER=native PROXY_DATABASE_PORT=3307 PROXY_DATABASE_TYPE=native PROXY_DATABASE_POOL_SIZE=30 PROXY_HTTP_PORT=9001 USER_FUNCTION_PORT=8090 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= iex --name spawn_a3@127.0.0.1 -S mix run-proxy-local-nodejs-test: ERL_ZFLAGS='-proto_dist inet_tls -ssl_dist_optfile rel/overlays/local-mtls.ssl.conf' cd spawn_proxy/proxy && mix deps.get && PROXY_DATABASE_TYPE=$(database) PROXY_HTTP_PORT=9001 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= PROXY_ACTOR_SYSTEM_NAME=SpawnSysTest SPAWN_SUPERVISORS_STATE_HANDOFF_CONTROLLER=crdt iex --name spawn_a1@test.default.svc -S mix diff --git a/examples/topology/host.yaml b/examples/topology/host.yaml index 2fe3b6a1..b44351a3 100644 --- a/examples/topology/host.yaml +++ b/examples/topology/host.yaml @@ -44,6 +44,14 @@ spec: # this configure podTemplate for Task Actors taskActors: - parentName: Jose + workerPool: + min: 0 + max: 10 + maxConcurrency: 100 + bootTimeout: 30000 + callTimeout: 30000 + oneShoot: "false" + idleShutdownAfter: 30000 topology: nodeSelector: gpu: "true" @@ -51,6 +59,7 @@ spec: - key: "gpu-machines" operator: "Exists" effect: "NoExecute" + resources: - parentName: Franchesco topology: nodeSelector: diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index a42e850d..a755ce0c 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -72,13 +72,18 @@ defmodule Actors.Actor.Entity do alias Eigr.Functions.Protocol.Actors.Actor alias Eigr.Functions.Protocol.Actors.ActorId + alias Eigr.Functions.Protocol.Actors.ActorSettings alias Eigr.Functions.Protocol.Actors.ActorState alias Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckReply alias Eigr.Functions.Protocol.Actors.Healthcheck.Status, as: HealthcheckStatus + alias Eigr.Functions.Protocol.InvocationRequest + alias Eigr.Functions.Protocol.State.Checkpoint alias Eigr.Functions.Protocol.State.Revision + alias Spawn.Cluster.Provisioner.Scheduler + import Spawn.Utils.Common, only: [return_and_maybe_hibernate: 1] @default_call_timeout :infinity @@ -128,9 +133,28 @@ defmodule Actors.Actor.Entity do state = EntityState.unpack(state) case action do - {:invocation_request, invocation, opts} -> + {:invocation_request, + %InvocationRequest{ + actor: + %Actor{id: %ActorId{name: actor_name} = _id, settings: %ActorSettings{kind: kind}} = + _actor + } = invocation, opts} -> opts = Keyword.merge(opts, from_pid: from) - Invocation.invoke({invocation, opts}, state) + # Check if actor is Task and call Invocation.invoke in remote POD. + IO.inspect(kind, label: "Kind ------------------") + case kind do + :TASK -> + Scheduler.schedule_and_invoke( + actor_name, + invocation, + opts, + state, + &Invocation.invoke/2 + ) + + _ -> + Invocation.invoke({invocation, opts}, state) + end action -> do_handle_defaults(action, from, state) diff --git a/lib/sidecar/grpc/dispatcher.ex b/lib/sidecar/grpc/dispatcher.ex index 863df9d2..4ec4c2b6 100644 --- a/lib/sidecar/grpc/dispatcher.ex +++ b/lib/sidecar/grpc/dispatcher.ex @@ -315,7 +315,6 @@ defmodule Sidecar.GRPC.Dispatcher do __pb_extensions__: ext } } -> - Map.get(ext, {Eigr.Functions.Protocol.Actors.PbExtension, :actor_id}, false) && {ctype, String.to_atom(name)} end) diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex index c2a95432..deef8b15 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/actor.pb.ex @@ -51,12 +51,12 @@ defmodule Eigr.Functions.Protocol.Actors.Kind do } end - field :UNKNOW_KIND, 0 - field :NAMED, 1 - field :UNNAMED, 2 - field :POOLED, 3 - field :PROXY, 4 - field :TASK, 5 + field(:UNKNOW_KIND, 0) + field(:NAMED, 1) + field(:UNNAMED, 2) + field(:POOLED, 3) + field(:PROXY, 4) + field(:TASK, 5) end defmodule Eigr.Functions.Protocol.Actors.Registry.ActorsEntry do @@ -118,8 +118,8 @@ defmodule Eigr.Functions.Protocol.Actors.Registry.ActorsEntry do } end - field :key, 1, type: :string - field :value, 2, type: Eigr.Functions.Protocol.Actors.Actor + field(:key, 1, type: :string) + field(:value, 2, type: Eigr.Functions.Protocol.Actors.Actor) end defmodule Eigr.Functions.Protocol.Actors.Registry do @@ -210,10 +210,11 @@ defmodule Eigr.Functions.Protocol.Actors.Registry do } end - field :actors, 1, + field(:actors, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.Registry.ActorsEntry, map: true + ) end defmodule Eigr.Functions.Protocol.Actors.ActorSystem do @@ -266,8 +267,8 @@ defmodule Eigr.Functions.Protocol.Actors.ActorSystem do } end - field :name, 1, type: :string - field :registry, 2, type: Eigr.Functions.Protocol.Actors.Registry + field(:name, 1, type: :string) + field(:registry, 2, type: Eigr.Functions.Protocol.Actors.Registry) end defmodule Eigr.Functions.Protocol.Actors.ActorSnapshotStrategy do @@ -312,9 +313,9 @@ defmodule Eigr.Functions.Protocol.Actors.ActorSnapshotStrategy do } end - oneof :strategy, 0 + oneof(:strategy, 0) - field :timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0 + field(:timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0) end defmodule Eigr.Functions.Protocol.Actors.ActorDeactivationStrategy do @@ -359,9 +360,9 @@ defmodule Eigr.Functions.Protocol.Actors.ActorDeactivationStrategy do } end - oneof :strategy, 0 + oneof(:strategy, 0) - field :timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0 + field(:timeout, 1, type: Eigr.Functions.Protocol.Actors.TimeoutStrategy, oneof: 0) end defmodule Eigr.Functions.Protocol.Actors.TimeoutStrategy do @@ -400,7 +401,7 @@ defmodule Eigr.Functions.Protocol.Actors.TimeoutStrategy do } end - field :timeout, 1, type: :int64 + field(:timeout, 1, type: :int64) end defmodule Eigr.Functions.Protocol.Actors.Action do @@ -439,7 +440,7 @@ defmodule Eigr.Functions.Protocol.Actors.Action do } end - field :name, 1, type: :string + field(:name, 1, type: :string) end defmodule Eigr.Functions.Protocol.Actors.FixedTimerAction do @@ -492,8 +493,8 @@ defmodule Eigr.Functions.Protocol.Actors.FixedTimerAction do } end - field :seconds, 1, type: :int32 - field :action, 2, type: Eigr.Functions.Protocol.Actors.Action + field(:seconds, 1, type: :int32) + field(:action, 2, type: Eigr.Functions.Protocol.Actors.Action) end defmodule Eigr.Functions.Protocol.Actors.ActorState.TagsEntry do @@ -555,8 +556,8 @@ defmodule Eigr.Functions.Protocol.Actors.ActorState.TagsEntry do } end - field :key, 1, type: :string - field :value, 2, type: :string + field(:key, 1, type: :string) + field(:value, 2, type: :string) end defmodule Eigr.Functions.Protocol.Actors.ActorState do @@ -661,12 +662,13 @@ defmodule Eigr.Functions.Protocol.Actors.ActorState do } end - field :tags, 1, + field(:tags, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.ActorState.TagsEntry, map: true + ) - field :state, 2, type: Google.Protobuf.Any + field(:state, 2, type: Google.Protobuf.Any) end defmodule Eigr.Functions.Protocol.Actors.Metadata.TagsEntry do @@ -728,8 +730,8 @@ defmodule Eigr.Functions.Protocol.Actors.Metadata.TagsEntry do } end - field :key, 1, type: :string - field :value, 2, type: :string + field(:key, 1, type: :string) + field(:value, 2, type: :string) end defmodule Eigr.Functions.Protocol.Actors.Metadata do @@ -834,15 +836,17 @@ defmodule Eigr.Functions.Protocol.Actors.Metadata do } end - field :channel_group, 1, + field(:channel_group, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.Channel, json_name: "channelGroup" + ) - field :tags, 2, + field(:tags, 2, repeated: true, type: Eigr.Functions.Protocol.Actors.Metadata.TagsEntry, map: true + ) end defmodule Eigr.Functions.Protocol.Actors.Channel do @@ -895,8 +899,8 @@ defmodule Eigr.Functions.Protocol.Actors.Channel do } end - field :topic, 1, type: :string - field :action, 2, type: :string + field(:topic, 1, type: :string) + field(:action, 2, type: :string) end defmodule Eigr.Functions.Protocol.Actors.ActorSettings do @@ -1005,19 +1009,21 @@ defmodule Eigr.Functions.Protocol.Actors.ActorSettings do } end - field :kind, 1, type: Eigr.Functions.Protocol.Actors.Kind, enum: true - field :stateful, 2, type: :bool + field(:kind, 1, type: Eigr.Functions.Protocol.Actors.Kind, enum: true) + field(:stateful, 2, type: :bool) - field :snapshot_strategy, 3, + field(:snapshot_strategy, 3, type: Eigr.Functions.Protocol.Actors.ActorSnapshotStrategy, json_name: "snapshotStrategy" + ) - field :deactivation_strategy, 4, + field(:deactivation_strategy, 4, type: Eigr.Functions.Protocol.Actors.ActorDeactivationStrategy, json_name: "deactivationStrategy" + ) - field :min_pool_size, 5, type: :int32, json_name: "minPoolSize" - field :max_pool_size, 6, type: :int32, json_name: "maxPoolSize" + field(:min_pool_size, 5, type: :int32, json_name: "minPoolSize") + field(:max_pool_size, 6, type: :int32, json_name: "maxPoolSize") end defmodule Eigr.Functions.Protocol.Actors.ActorId do @@ -1084,9 +1090,9 @@ defmodule Eigr.Functions.Protocol.Actors.ActorId do } end - field :name, 1, type: :string - field :system, 2, type: :string - field :parent, 3, type: :string + field(:name, 1, type: :string) + field(:system, 2, type: :string) + field(:parent, 3, type: :string) end defmodule Eigr.Functions.Protocol.Actors.Actor do @@ -1195,14 +1201,15 @@ defmodule Eigr.Functions.Protocol.Actors.Actor do } end - field :id, 1, type: Eigr.Functions.Protocol.Actors.ActorId - field :state, 2, type: Eigr.Functions.Protocol.Actors.ActorState - field :metadata, 6, type: Eigr.Functions.Protocol.Actors.Metadata - field :settings, 3, type: Eigr.Functions.Protocol.Actors.ActorSettings - field :actions, 4, repeated: true, type: Eigr.Functions.Protocol.Actors.Action + field(:id, 1, type: Eigr.Functions.Protocol.Actors.ActorId) + field(:state, 2, type: Eigr.Functions.Protocol.Actors.ActorState) + field(:metadata, 6, type: Eigr.Functions.Protocol.Actors.Metadata) + field(:settings, 3, type: Eigr.Functions.Protocol.Actors.ActorSettings) + field(:actions, 4, repeated: true, type: Eigr.Functions.Protocol.Actors.Action) - field :timer_actions, 5, + field(:timer_actions, 5, repeated: true, type: Eigr.Functions.Protocol.Actors.FixedTimerAction, json_name: "timerActions" -end \ No newline at end of file + ) +end diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex index 5e96b9b6..55549a42 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/extensions.pb.ex @@ -2,8 +2,9 @@ defmodule Eigr.Functions.Protocol.Actors.PbExtension do @moduledoc false use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3 - extend Google.Protobuf.FieldOptions, :actor_id, 9999, + extend(Google.Protobuf.FieldOptions, :actor_id, 9999, optional: true, type: :bool, json_name: "actorId" -end \ No newline at end of file + ) +end diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex index 213388f2..ff2b7d2d 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/healthcheck.pb.ex @@ -62,9 +62,9 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.Status do } end - field :status, 1, type: :string - field :details, 2, type: :string - field :updated_at, 3, type: Google.Protobuf.Timestamp, json_name: "updatedAt" + field(:status, 1, type: :string) + field(:details, 2, type: :string) + field(:updated_at, 3, type: Google.Protobuf.Timestamp, json_name: "updatedAt") end defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckReply do @@ -103,7 +103,7 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckReply do } end - field :status, 1, type: Eigr.Functions.Protocol.Actors.Healthcheck.Status + field(:status, 1, type: Eigr.Functions.Protocol.Actors.Healthcheck.Status) end defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service do @@ -694,4 +694,4 @@ defmodule Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Stub do @moduledoc false use GRPC.Stub, service: Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckActor.Service -end \ No newline at end of file +end diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex index 7a3c939c..aabfd02f 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/protocol.pb.ex @@ -39,10 +39,10 @@ defmodule Eigr.Functions.Protocol.Status do } end - field :UNKNOWN, 0 - field :OK, 1 - field :ACTOR_NOT_FOUND, 2 - field :ERROR, 3 + field(:UNKNOWN, 0) + field(:OK, 1) + field(:ACTOR_NOT_FOUND, 2) + field(:ERROR, 3) end defmodule Eigr.Functions.Protocol.Context.MetadataEntry do @@ -104,8 +104,8 @@ defmodule Eigr.Functions.Protocol.Context.MetadataEntry do } end - field :key, 1, type: :string - field :value, 2, type: :string + field(:key, 1, type: :string) + field(:value, 2, type: :string) end defmodule Eigr.Functions.Protocol.Context.TagsEntry do @@ -167,8 +167,8 @@ defmodule Eigr.Functions.Protocol.Context.TagsEntry do } end - field :key, 1, type: :string - field :value, 2, type: :string + field(:key, 1, type: :string) + field(:value, 2, type: :string) end defmodule Eigr.Functions.Protocol.Context do @@ -366,16 +366,17 @@ defmodule Eigr.Functions.Protocol.Context do } end - field :state, 1, type: Google.Protobuf.Any + field(:state, 1, type: Google.Protobuf.Any) - field :metadata, 4, + field(:metadata, 4, repeated: true, type: Eigr.Functions.Protocol.Context.MetadataEntry, map: true + ) - field :tags, 5, repeated: true, type: Eigr.Functions.Protocol.Context.TagsEntry, map: true - field :caller, 2, type: Eigr.Functions.Protocol.Actors.ActorId - field :self, 3, type: Eigr.Functions.Protocol.Actors.ActorId + field(:tags, 5, repeated: true, type: Eigr.Functions.Protocol.Context.TagsEntry, map: true) + field(:caller, 2, type: Eigr.Functions.Protocol.Actors.ActorId) + field(:self, 3, type: Eigr.Functions.Protocol.Actors.ActorId) end defmodule Eigr.Functions.Protocol.Noop do @@ -436,7 +437,7 @@ defmodule Eigr.Functions.Protocol.JSONType do } end - field :content, 1, type: :string + field(:content, 1, type: :string) end defmodule Eigr.Functions.Protocol.RegistrationRequest do @@ -489,11 +490,12 @@ defmodule Eigr.Functions.Protocol.RegistrationRequest do } end - field :service_info, 1, type: Eigr.Functions.Protocol.ServiceInfo, json_name: "serviceInfo" + field(:service_info, 1, type: Eigr.Functions.Protocol.ServiceInfo, json_name: "serviceInfo") - field :actor_system, 2, + field(:actor_system, 2, type: Eigr.Functions.Protocol.Actors.ActorSystem, json_name: "actorSystem" + ) end defmodule Eigr.Functions.Protocol.RegistrationResponse do @@ -546,8 +548,8 @@ defmodule Eigr.Functions.Protocol.RegistrationResponse do } end - field :status, 1, type: Eigr.Functions.Protocol.RequestStatus - field :proxy_info, 2, type: Eigr.Functions.Protocol.ProxyInfo, json_name: "proxyInfo" + field(:status, 1, type: Eigr.Functions.Protocol.RequestStatus) + field(:proxy_info, 2, type: Eigr.Functions.Protocol.ProxyInfo, json_name: "proxyInfo") end defmodule Eigr.Functions.Protocol.ServiceInfo do @@ -670,13 +672,13 @@ defmodule Eigr.Functions.Protocol.ServiceInfo do } end - field :service_name, 1, type: :string, json_name: "serviceName" - field :service_version, 2, type: :string, json_name: "serviceVersion" - field :service_runtime, 3, type: :string, json_name: "serviceRuntime" - field :support_library_name, 4, type: :string, json_name: "supportLibraryName" - field :support_library_version, 5, type: :string, json_name: "supportLibraryVersion" - field :protocol_major_version, 6, type: :int32, json_name: "protocolMajorVersion" - field :protocol_minor_version, 7, type: :int32, json_name: "protocolMinorVersion" + field(:service_name, 1, type: :string, json_name: "serviceName") + field(:service_version, 2, type: :string, json_name: "serviceVersion") + field(:service_runtime, 3, type: :string, json_name: "serviceRuntime") + field(:support_library_name, 4, type: :string, json_name: "supportLibraryName") + field(:support_library_version, 5, type: :string, json_name: "supportLibraryVersion") + field(:protocol_major_version, 6, type: :int32, json_name: "protocolMajorVersion") + field(:protocol_minor_version, 7, type: :int32, json_name: "protocolMinorVersion") end defmodule Eigr.Functions.Protocol.SpawnRequest do @@ -715,7 +717,7 @@ defmodule Eigr.Functions.Protocol.SpawnRequest do } end - field :actors, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.ActorId + field(:actors, 1, repeated: true, type: Eigr.Functions.Protocol.Actors.ActorId) end defmodule Eigr.Functions.Protocol.SpawnResponse do @@ -754,7 +756,7 @@ defmodule Eigr.Functions.Protocol.SpawnResponse do } end - field :status, 1, type: Eigr.Functions.Protocol.RequestStatus + field(:status, 1, type: Eigr.Functions.Protocol.RequestStatus) end defmodule Eigr.Functions.Protocol.ProxyInfo do @@ -835,10 +837,10 @@ defmodule Eigr.Functions.Protocol.ProxyInfo do } end - field :protocol_major_version, 1, type: :int32, json_name: "protocolMajorVersion" - field :protocol_minor_version, 2, type: :int32, json_name: "protocolMinorVersion" - field :proxy_name, 3, type: :string, json_name: "proxyName" - field :proxy_version, 4, type: :string, json_name: "proxyVersion" + field(:protocol_major_version, 1, type: :int32, json_name: "protocolMajorVersion") + field(:protocol_minor_version, 2, type: :int32, json_name: "protocolMinorVersion") + field(:proxy_name, 3, type: :string, json_name: "proxyName") + field(:proxy_version, 4, type: :string, json_name: "proxyVersion") end defmodule Eigr.Functions.Protocol.SideEffect do @@ -877,7 +879,7 @@ defmodule Eigr.Functions.Protocol.SideEffect do } end - field :request, 1, type: Eigr.Functions.Protocol.InvocationRequest + field(:request, 1, type: Eigr.Functions.Protocol.InvocationRequest) end defmodule Eigr.Functions.Protocol.Broadcast do @@ -950,11 +952,11 @@ defmodule Eigr.Functions.Protocol.Broadcast do } end - oneof :payload, 0 + oneof(:payload, 0) - field :channel_group, 1, type: :string, json_name: "channelGroup" - field :value, 3, type: Google.Protobuf.Any, oneof: 0 - field :noop, 4, type: Eigr.Functions.Protocol.Noop, oneof: 0 + field(:channel_group, 1, type: :string, json_name: "channelGroup") + field(:value, 3, type: Google.Protobuf.Any, oneof: 0) + field(:noop, 4, type: Eigr.Functions.Protocol.Noop, oneof: 0) end defmodule Eigr.Functions.Protocol.Pipe do @@ -1007,8 +1009,8 @@ defmodule Eigr.Functions.Protocol.Pipe do } end - field :actor, 1, type: :string - field :action_name, 2, type: :string, json_name: "actionName" + field(:actor, 1, type: :string) + field(:action_name, 2, type: :string, json_name: "actionName") end defmodule Eigr.Functions.Protocol.Forward do @@ -1061,8 +1063,8 @@ defmodule Eigr.Functions.Protocol.Forward do } end - field :actor, 1, type: :string - field :action_name, 2, type: :string, json_name: "actionName" + field(:actor, 1, type: :string) + field(:action_name, 2, type: :string, json_name: "actionName") end defmodule Eigr.Functions.Protocol.Workflow do @@ -1149,12 +1151,12 @@ defmodule Eigr.Functions.Protocol.Workflow do } end - oneof :routing, 0 + oneof(:routing, 0) - field :broadcast, 2, type: Eigr.Functions.Protocol.Broadcast - field :effects, 1, repeated: true, type: Eigr.Functions.Protocol.SideEffect - field :pipe, 3, type: Eigr.Functions.Protocol.Pipe, oneof: 0 - field :forward, 4, type: Eigr.Functions.Protocol.Forward, oneof: 0 + field(:broadcast, 2, type: Eigr.Functions.Protocol.Broadcast) + field(:effects, 1, repeated: true, type: Eigr.Functions.Protocol.SideEffect) + field(:pipe, 3, type: Eigr.Functions.Protocol.Pipe, oneof: 0) + field(:forward, 4, type: Eigr.Functions.Protocol.Forward, oneof: 0) end defmodule Eigr.Functions.Protocol.InvocationRequest.MetadataEntry do @@ -1216,8 +1218,8 @@ defmodule Eigr.Functions.Protocol.InvocationRequest.MetadataEntry do } end - field :key, 1, type: :string - field :value, 2, type: :string + field(:key, 1, type: :string) + field(:value, 2, type: :string) end defmodule Eigr.Functions.Protocol.InvocationRequest do @@ -1454,24 +1456,25 @@ defmodule Eigr.Functions.Protocol.InvocationRequest do } end - oneof :payload, 0 + oneof(:payload, 0) - field :system, 1, type: Eigr.Functions.Protocol.Actors.ActorSystem - field :actor, 2, type: Eigr.Functions.Protocol.Actors.Actor - field :action_name, 3, type: :string, json_name: "actionName" - field :value, 4, type: Google.Protobuf.Any, oneof: 0 - field :noop, 7, type: Eigr.Functions.Protocol.Noop, oneof: 0 - field :async, 5, type: :bool - field :caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId + field(:system, 1, type: Eigr.Functions.Protocol.Actors.ActorSystem) + field(:actor, 2, type: Eigr.Functions.Protocol.Actors.Actor) + field(:action_name, 3, type: :string, json_name: "actionName") + field(:value, 4, type: Google.Protobuf.Any, oneof: 0) + field(:noop, 7, type: Eigr.Functions.Protocol.Noop, oneof: 0) + field(:async, 5, type: :bool) + field(:caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId) - field :metadata, 8, + field(:metadata, 8, repeated: true, type: Eigr.Functions.Protocol.InvocationRequest.MetadataEntry, map: true + ) - field :scheduled_to, 9, type: :int64, json_name: "scheduledTo" - field :pooled, 10, type: :bool - field :register_ref, 11, type: :string, json_name: "registerRef" + field(:scheduled_to, 9, type: :int64, json_name: "scheduledTo") + field(:pooled, 10, type: :bool) + field(:register_ref, 11, type: :string, json_name: "registerRef") end defmodule Eigr.Functions.Protocol.ActorInvocation do @@ -1586,14 +1589,14 @@ defmodule Eigr.Functions.Protocol.ActorInvocation do } end - oneof :payload, 0 + oneof(:payload, 0) - field :actor, 1, type: Eigr.Functions.Protocol.Actors.ActorId - field :action_name, 2, type: :string, json_name: "actionName" - field :current_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "currentContext" - field :value, 4, type: Google.Protobuf.Any, oneof: 0 - field :noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0 - field :caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId + field(:actor, 1, type: Eigr.Functions.Protocol.Actors.ActorId) + field(:action_name, 2, type: :string, json_name: "actionName") + field(:current_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "currentContext") + field(:value, 4, type: Google.Protobuf.Any, oneof: 0) + field(:noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0) + field(:caller, 6, type: Eigr.Functions.Protocol.Actors.ActorId) end defmodule Eigr.Functions.Protocol.ActorInvocationResponse do @@ -1722,15 +1725,15 @@ defmodule Eigr.Functions.Protocol.ActorInvocationResponse do } end - oneof :payload, 0 + oneof(:payload, 0) - field :actor_name, 1, type: :string, json_name: "actorName" - field :actor_system, 2, type: :string, json_name: "actorSystem" - field :updated_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "updatedContext" - field :value, 4, type: Google.Protobuf.Any, oneof: 0 - field :noop, 6, type: Eigr.Functions.Protocol.Noop, oneof: 0 - field :workflow, 5, type: Eigr.Functions.Protocol.Workflow - field :checkpoint, 7, type: :bool + field(:actor_name, 1, type: :string, json_name: "actorName") + field(:actor_system, 2, type: :string, json_name: "actorSystem") + field(:updated_context, 3, type: Eigr.Functions.Protocol.Context, json_name: "updatedContext") + field(:value, 4, type: Google.Protobuf.Any, oneof: 0) + field(:noop, 6, type: Eigr.Functions.Protocol.Noop, oneof: 0) + field(:workflow, 5, type: Eigr.Functions.Protocol.Workflow) + field(:checkpoint, 7, type: :bool) end defmodule Eigr.Functions.Protocol.InvocationResponse do @@ -1831,13 +1834,13 @@ defmodule Eigr.Functions.Protocol.InvocationResponse do } end - oneof :payload, 0 + oneof(:payload, 0) - field :status, 1, type: Eigr.Functions.Protocol.RequestStatus - field :system, 2, type: Eigr.Functions.Protocol.Actors.ActorSystem - field :actor, 3, type: Eigr.Functions.Protocol.Actors.Actor - field :value, 4, type: Google.Protobuf.Any, oneof: 0 - field :noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0 + field(:status, 1, type: Eigr.Functions.Protocol.RequestStatus) + field(:system, 2, type: Eigr.Functions.Protocol.Actors.ActorSystem) + field(:actor, 3, type: Eigr.Functions.Protocol.Actors.Actor) + field(:value, 4, type: Google.Protobuf.Any, oneof: 0) + field(:noop, 5, type: Eigr.Functions.Protocol.Noop, oneof: 0) end defmodule Eigr.Functions.Protocol.RequestStatus do @@ -1890,6 +1893,6 @@ defmodule Eigr.Functions.Protocol.RequestStatus do } end - field :status, 1, type: Eigr.Functions.Protocol.Status, enum: true - field :message, 2, type: :string -end \ No newline at end of file + field(:status, 1, type: Eigr.Functions.Protocol.Status, enum: true) + field(:message, 2, type: :string) +end diff --git a/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex b/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex index 7a57ec71..92915b44 100644 --- a/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex +++ b/lib/spawn/actors/eigr/functions/protocol/actors/state.pb.ex @@ -34,7 +34,7 @@ defmodule Eigr.Functions.Protocol.State.Revision do } end - field :value, 1, type: :int64 + field(:value, 1, type: :int64) end defmodule Eigr.Functions.Protocol.State.Checkpoint do @@ -87,6 +87,6 @@ defmodule Eigr.Functions.Protocol.State.Checkpoint do } end - field :revision, 1, type: Eigr.Functions.Protocol.State.Revision - field :state, 2, type: Eigr.Functions.Protocol.Actors.ActorState -end \ No newline at end of file + field(:revision, 1, type: Eigr.Functions.Protocol.State.Revision) + field(:state, 2, type: Eigr.Functions.Protocol.Actors.ActorState) +end diff --git a/lib/spawn/cluster/cluster_supervisor.ex b/lib/spawn/cluster/cluster_supervisor.ex index a238740e..1a18ecf2 100644 --- a/lib/spawn/cluster/cluster_supervisor.ex +++ b/lib/spawn/cluster/cluster_supervisor.ex @@ -15,14 +15,21 @@ defmodule Spawn.Cluster.ClusterSupervisor do @impl true def init(opts) do - children = [ - supervisor_process_logger(__MODULE__), - cluster_supervisor(opts) - ] + children = + [ + supervisor_process_logger(__MODULE__), + cluster_supervisor(opts) + ] + |> maybe_add_provisioner(opts) Supervisor.init(children, strategy: :one_for_one) end + defp maybe_add_provisioner(children, opts) do + # TODO check if is production env + children ++ [{Spawn.Cluster.ProvisionerPoolSupervisor, opts}] + end + defp cluster_supervisor(opts) do cluster_strategy = Config.get(:proxy_cluster_strategy) diff --git a/lib/spawn/cluster/provisioner/scheduler.ex b/lib/spawn/cluster/provisioner/scheduler.ex new file mode 100644 index 00000000..bc1e649d --- /dev/null +++ b/lib/spawn/cluster/provisioner/scheduler.ex @@ -0,0 +1,9 @@ +defmodule Spawn.Cluster.Provisioner.Scheduler do + 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) + end +end diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex new file mode 100644 index 00000000..33e011de --- /dev/null +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -0,0 +1,131 @@ +defmodule Spawn.Cluster.ProvisionerPoolSupervisor do + @moduledoc false + use Supervisor + require Logger + + import Spawn.Utils.Common, only: [build_worker_pool_name: 2] + + def start_link(opts) do + Supervisor.start_link(__MODULE__, opts, name: __MODULE__) + end + + @impl true + def init(_opts) do + actor_configs = + System.get_env("SPAWN_PROXY_TASK_CONFIG", "") + |> parse_config() + + env = get_environment() + + children = + Enum.map(actor_configs, fn cfg -> + Logger.info("Setup Task Actor with config: #{inspect(cfg)}") + + cfg + |> build_pod_template() + |> build_flame_pool(cfg, env) + end) + + Supervisor.init(children, strategy: :one_for_one) + end + + defp parse_config(""), do: [] + + defp parse_config(encoded_cfg) do + encoded_cfg + |> Base.decode32!() + |> Jason.decode!() + |> Map.get("taskActors", []) + end + + defp get_environment do + case System.get_env("MIX_ENV", "dev") do + "prod" -> :prod + env -> String.to_atom(env) + end + end + + defp build_pod_template(%{"topology" => topology} = _cfg) do + %{} + |> maybe_put_node_selector(topology) + |> maybe_put_toleration(topology) + end + + defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do + Map.merge(template, %{ + "metadata" => %{ + "labels" => %{"io.eigr.spawn/worker" => "true"} + }, + "spec" => %{"nodeSelector" => selector} + }) + end + + defp maybe_put_node_selector(template, _topology), do: template + + defp maybe_put_toleration(template, %{"tolerations" => toleration}) do + Map.merge(template, %{ + "metadata" => %{ + "labels" => %{"io.eigr.spawn/worker" => "true"} + }, + "spec" => %{"tolerations" => toleration} + }) + end + + defp maybe_put_toleration(template, _topology), do: template + + defp build_flame_pool(pod_template, %{"parentName" => name} = cfg, :prod) do + pool_name = build_worker_pool_name(__MODULE__, name) + Logger.info("Create pool for parent Actor #{name}. Pool Name #{inspect(pool_name)}") + + opts = + [ + name: pool_name, + backend: {FLAMEK8sBackend, runner_pod_tpl: pod_template}, + log: :debug + ] ++ get_worker_pool_config(cfg) + + {FLAME.Pool, opts} + end + + defp build_flame_pool(_pod_template, %{"parentName" => name} = cfg, _env) do + pool_name = build_worker_pool_name(__MODULE__, name) + Logger.info("Creating default pool with name #{inspect(pool_name)}") + + opts = + [ + name: pool_name, + backend: FLAME.LocalBackend, + log: :debug + ] ++ get_worker_pool_config(cfg) + + {FLAME.Pool, opts} + end + + defp build_flame_pool(_pod_template, cfg, _env) do + pool_name = Module.concat(__MODULE__, "Default") + Logger.info("Creating default pool with name #{inspect(pool_name)}") + + opts = + [ + name: pool_name, + backend: FLAME.LocalBackend, + log: :debug + ] ++ get_worker_pool_config(cfg) + + {FLAME.Pool, opts} + end + + defp get_worker_pool_config(cfg) do + worker_pool_config = Map.get(cfg, "workerPool", %{}) + + [ + min: Map.get(worker_pool_config, "min", 0), + max: Map.get(worker_pool_config, "max", 10), + max_concurrency: Map.get(worker_pool_config, "maxConcurrency", 100), + boot_timeout: Map.get(worker_pool_config, "bootTimeout", 30000), + timeout: Map.get(worker_pool_config, "callTimeout", 30000), + single_use: Map.get(worker_pool_config, "oneShoot", "false"), + idle_shutdown_after: Map.get(worker_pool_config, "idleShutdownAfter", 30000) + ] + end +end diff --git a/lib/spawn/utils/common.ex b/lib/spawn/utils/common.ex index 7fa8e52b..5b96182c 100644 --- a/lib/spawn/utils/common.ex +++ b/lib/spawn/utils/common.ex @@ -5,6 +5,10 @@ defmodule Spawn.Utils.Common do alias Actors.Config.PersistentTermConfig, as: Config alias Eigr.Functions.Protocol.Actors.ActorId + def build_worker_pool_name(module, parent) do + Module.concat(module, String.upcase(parent)) + end + @spec actor_host_hash() :: integer() def actor_host_hash() do system = Config.get(:actor_system_name) diff --git a/mix.exs b/mix.exs index 2582fb83..63a66844 100644 --- a/mix.exs +++ b/mix.exs @@ -80,6 +80,7 @@ defmodule Spawn.MixProject do {:grpc, "~> 0.8"}, {:grpc_reflection, "~> 0.1"}, {:finch, "~> 0.18"}, + {:flame_k8s_backend, "~> 0.5"}, {:retry, "~> 0.17"}, {:flow, "~> 1.2"}, {:libcluster, "~> 3.3"}, diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index 0a9c60ed..e24c87a8 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -71,6 +71,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do ) do host_params = Map.get(params, "host") task_actors_config = %{"taskActors" => Map.get(host_params, "taskActors", %{})} + IO.inspect(task_actors_config, label: "Config ------------------------") topology = Map.get(params, "topology", %{}) replicas = max(1, Map.get(params, "replicas", @default_actor_host_function_replicas)) @@ -198,17 +199,6 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do } end - defp build_task_env(task_actors_config) do - value = - task_actors_config - |> Jason.encode!() - |> Base.encode32() - - [ - %{"name" => "SPAWN_PROXY_TASK_CONFIG", "value" => value} - ] - end - defp get_containers(true, system, name, host_params, annotations, task_actors_config) do actor_host_function_image = Map.get(host_params, "image") @@ -348,6 +338,17 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do ] end + defp build_task_env(task_actors_config) do + value = + task_actors_config + |> Jason.encode!() + |> Base.encode32() + + [ + %{"name" => "SPAWN_PROXY_TASK_CONFIG", "value" => value} + ] + end + defp maybe_put_node_selector(spec, %{"nodeSelector" => selectors} = _topology) do Map.merge(spec, %{"nodeSelector" => selectors}) end diff --git a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs index 8a64a545..d92020c1 100644 --- a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs +++ b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs @@ -417,7 +417,11 @@ defmodule DeploymentTest do %{"name" => "SPAWN_PROXY_INTERFACE", "value" => "0.0.0.0"}, %{"name" => "RELEASE_DISTRIBUTION", "value" => "name"}, %{"name" => "RELEASE_NODE", "value" => "$(RELEASE_NAME)@$(POD_IP)"}, - %{"name" => "SPAWN_PROXY_TASK_CONFIG", "value" => "PMRHIYLTNNAWG5DPOJZSEOS3PMRHAYLSMVXHITTBNVSSEORCJJXXGZJCFQRHI33QN5WG6Z3ZEI5HWITON5SGKU3FNRSWG5DPOIRDU6ZCM5YHKIR2EJTGC3DTMURH27L5LV6Q===="} + %{ + "name" => "SPAWN_PROXY_TASK_CONFIG", + "value" => + "PMRHIYLTNNAWG5DPOJZSEOS3PMRHAYLSMVXHITTBNVSSEORCJJXXGZJCFQRHI33QN5WG6Z3ZEI5HWITON5SGKU3FNRSWG5DPOIRDU6ZCM5YHKIR2EJTGC3DTMURH27L5LV6Q====" + } ], "envFrom" => [ %{"configMapRef" => %{"name" => "spawn-test-sidecar-cm"}}, diff --git a/spawn_proxy/proxy/mix.exs b/spawn_proxy/proxy/mix.exs index 9f5bd275..fa80adf7 100644 --- a/spawn_proxy/proxy/mix.exs +++ b/spawn_proxy/proxy/mix.exs @@ -38,7 +38,6 @@ defmodule Proxy.MixProject do path: "../../spawn_statestores/statestores_native", optional: false}, {:bakeware, "~> 0.2"}, {:bandit, "~> 1.5"}, - {:flame_k8s_backend, "~> 0.5.4"}, {:observer_cli, "~> 1.7"}, {:sobelow, "~> 0.13", only: [:dev, :test], runtime: false} ] diff --git a/test/actors/actors_test.exs b/test/actors/actors_test.exs index 770ba2a9..845d731f 100644 --- a/test/actors/actors_test.exs +++ b/test/actors/actors_test.exs @@ -111,6 +111,30 @@ defmodule ActorsTest do Actors.invoke(invoke_request) end + test "invoke task actor function for a newly registered actor" do + actor_name = "Jose" + + actor = build_actor(name: actor_name, kind: :TASK) + actor_entry = build_actor_entry(name: actor_name, actor: actor) + registry = build_registry_with_actors(actors: actor_entry) + system = build_system(registry: registry) + + request = build_registration_request(actor_system: system) + + {:ok, %RegistrationResponse{}} = Actors.register(request) + + # invoke + invoke_request = build_invocation_request(system: system, actor: actor) + + host_invoke_response = + build_host_invoke_response(actor_name: actor_name, system_name: system.name) + + mock_invoke_host_actor_with_ok_response(host_invoke_response) + + assert {:ok, %ActorInvocationResponse{actor_name: ^actor_name}} = + Actors.invoke(invoke_request) + end + @tag :skip test "invoke actor function for a already registered actor in another node", ctx do %{system: system, actor: actor} = ctx diff --git a/test/support/factory.ex b/test/support/factory.ex index ec731d25..484da6ca 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -99,6 +99,7 @@ defmodule Actors.FactoryTest do id: %ActorId{name: actor_name, system: attrs[:system]}, actions: attrs[:actions] || [build_actor_action()], settings: %ActorSettings{ + kind: Keyword.get(attrs, :kind, :NAMED), stateful: Keyword.get(attrs, :stateful, true), snapshot_strategy: attrs[:snapshot_strategy] || build_actor_snapshot_strategy(), deactivation_strategy: From ac2289aeeb12c9e2f5692759301555b582f98b34 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 03:52:49 -0300 Subject: [PATCH 07/34] Some debug message --- test/actors/actors_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/actors/actors_test.exs b/test/actors/actors_test.exs index 845d731f..4ba78a1d 100644 --- a/test/actors/actors_test.exs +++ b/test/actors/actors_test.exs @@ -132,7 +132,7 @@ defmodule ActorsTest do mock_invoke_host_actor_with_ok_response(host_invoke_response) assert {:ok, %ActorInvocationResponse{actor_name: ^actor_name}} = - Actors.invoke(invoke_request) + Actors.invoke(invoke_request) |> IO.inspect(label: "Remote response") end @tag :skip From 1012de998d48a1ba79014018ddaca2e7a03f25c6 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 10:21:44 -0300 Subject: [PATCH 08/34] Added comment about scheduler and remote invocations --- lib/actors/actor/entity/entity.ex | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index a755ce0c..c9c2b86c 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -141,7 +141,15 @@ defmodule Actors.Actor.Entity do } = invocation, opts} -> opts = Keyword.merge(opts, from_pid: from) # Check if actor is Task and call Invocation.invoke in remote POD. - IO.inspect(kind, label: "Kind ------------------") + # This code is executed here to ensure that a real instance of the target actor is present locally. + # On the remote node, the code will run with communication to the ActorHost happening locally via the + # sidecar. However, the return of the call will be directed to this process, + # allowing the local state to be updated, even though the execution occurred remotely. + + # In synchronous calls, this also ensures that the deactivate timeout will not be impacted. + # If this process fails, it is likely that Scheduler via Flame will terminate the remote process. + # We still need to perform more tests to understand how this will affect the system. + # The same applies to asynchronous calls. case kind do :TASK -> Scheduler.schedule_and_invoke( From c6f6056ed2c597c99917939e9fb560d6ff8daae3 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 11:36:54 -0300 Subject: [PATCH 09/34] Refactor to use protocol --- lib/actors/actor/entity/entity.ex | 16 ++--- lib/spawn/cluster/provisioner/executor.ex | 4 ++ lib/spawn/cluster/provisioner/scheduler.ex | 66 ++++++++++++++++++++- lib/spawn/cluster/provisioner/spawn_task.ex | 3 + 4 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 lib/spawn/cluster/provisioner/executor.ex create mode 100644 lib/spawn/cluster/provisioner/spawn_task.ex diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index c9c2b86c..b364cc6f 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -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] @@ -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) diff --git a/lib/spawn/cluster/provisioner/executor.ex b/lib/spawn/cluster/provisioner/executor.ex new file mode 100644 index 00000000..01feb3fa --- /dev/null +++ b/lib/spawn/cluster/provisioner/executor.ex @@ -0,0 +1,4 @@ +defprotocol Spawn.Cluster.Provisioner.Executor do + @doc "Executes a task" + def execute(task, func) +end diff --git a/lib/spawn/cluster/provisioner/scheduler.ex b/lib/spawn/cluster/provisioner/scheduler.ex index bc1e649d..e9bdd48d 100644 --- a/lib/spawn/cluster/provisioner/scheduler.ex +++ b/lib/spawn/cluster/provisioner/scheduler.ex @@ -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 """ + 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 diff --git a/lib/spawn/cluster/provisioner/spawn_task.ex b/lib/spawn/cluster/provisioner/spawn_task.ex new file mode 100644 index 00000000..487725c6 --- /dev/null +++ b/lib/spawn/cluster/provisioner/spawn_task.ex @@ -0,0 +1,3 @@ +defmodule Spawn.Cluster.Provisioner.SpawnTask do + defstruct [:parent, :invocation, :opts, :state] +end From ee2b6301bf6fd0af14bfe0cd46f02e0b3c930a86 Mon Sep 17 00:00:00 2001 From: eliasdarruda Date: Mon, 30 Sep 2024 14:22:57 -0300 Subject: [PATCH 10/34] rename and adjust invocation handle_call from state instead of invocationrequest --- examples/topology/host.yaml | 4 +-- lib/actors/actor/entity/entity.ex | 14 ++------ lib/spawn/cluster/provisioner/scheduler.ex | 33 ++++++++++--------- lib/spawn/cluster/provisioner/spawn_task.ex | 2 +- .../cluster/provisioner_pool_supervisor.ex | 6 ++-- .../spawn_operator/test/support/factory.ex | 2 +- 6 files changed, 28 insertions(+), 33 deletions(-) diff --git a/examples/topology/host.yaml b/examples/topology/host.yaml index b44351a3..79d626e4 100644 --- a/examples/topology/host.yaml +++ b/examples/topology/host.yaml @@ -43,7 +43,7 @@ spec: image: eigr/spawn-springboot-examples:0.5.5 # Mandatory # this configure podTemplate for Task Actors taskActors: - - parentName: Jose + - actorName: Jose workerPool: min: 0 max: 10 @@ -60,7 +60,7 @@ spec: operator: "Exists" effect: "NoExecute" resources: - - parentName: Franchesco + - actorName: Franchesco topology: nodeSelector: beam: "true" diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index b364cc6f..2fa029a8 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -72,13 +72,10 @@ defmodule Actors.Actor.Entity do alias Eigr.Functions.Protocol.Actors.Actor alias Eigr.Functions.Protocol.Actors.ActorId - alias Eigr.Functions.Protocol.Actors.ActorSettings alias Eigr.Functions.Protocol.Actors.ActorState alias Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckReply alias Eigr.Functions.Protocol.Actors.Healthcheck.Status, as: HealthcheckStatus - alias Eigr.Functions.Protocol.InvocationRequest - alias Eigr.Functions.Protocol.State.Checkpoint alias Eigr.Functions.Protocol.State.Revision @@ -134,12 +131,7 @@ defmodule Actors.Actor.Entity do state = EntityState.unpack(state) case action do - {:invocation_request, - %InvocationRequest{ - actor: - %Actor{id: %ActorId{name: actor_name} = _id, settings: %ActorSettings{kind: kind}} = - _actor - } = invocation, opts} -> + {:invocation_request, invocation, opts} -> opts = Keyword.merge(opts, from_pid: from) # Check if actor is Task and call Invocation.invoke in remote POD. # This code is executed here to ensure that a real instance of the target actor is present locally. @@ -151,10 +143,10 @@ defmodule Actors.Actor.Entity do # If this process fails, it is likely that Scheduler via Flame will terminate the remote process. # We still need to perform more tests to understand how this will affect the system. # The same applies to asynchronous calls. - case kind do + case state.actor.settings.kind do :TASK -> task = %SpawnTask{ - parent: actor_name, + actor_name: state.actor.id.name, invocation: invocation, opts: opts, state: state diff --git a/lib/spawn/cluster/provisioner/scheduler.ex b/lib/spawn/cluster/provisioner/scheduler.ex index e9bdd48d..af6f8fb7 100644 --- a/lib/spawn/cluster/provisioner/scheduler.ex +++ b/lib/spawn/cluster/provisioner/scheduler.ex @@ -11,28 +11,31 @@ defmodule Spawn.Cluster.Provisioner.Scheduler do alias Spawn.Cluster.ProvisionerPoolSupervisor import Spawn.Utils.Common, only: [build_worker_pool_name: 2] - @doc """ - Defines the `Executor` protocol for the `SpawnTask` struct. + defimpl Spawn.Cluster.Provisioner.Executor, for: Spawn.Cluster.Provisioner.SpawnTask do + @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. + This implementation handles the execution of a given function (`func`) in the context of a task, + using the specified actor name, 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. + 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 + ## 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 + ## 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) + The result of executing the provided function within the context of the actor provisioning system. + """ + def execute( + %SpawnTask{actor_name: actor_name, invocation: invocation, opts: opts, state: state}, + func + ) when is_function(func) do - build_worker_pool_name(ProvisionerPoolSupervisor, parent) + build_worker_pool_name(ProvisionerPoolSupervisor, actor_name) |> FLAME.call(fn -> func.({invocation, opts}, state) end) end end @@ -45,7 +48,7 @@ defmodule Spawn.Cluster.Provisioner.Scheduler do ## Parameters - - `parent`: The parent reference used to create the worker pool for the task execution. + - `actor_name`: The actor name 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. @@ -55,7 +58,7 @@ defmodule Spawn.Cluster.Provisioner.Scheduler do ```elixir task = %SpawnTask{ - parent: parent, + actor: actor, invocation: invocation, opts: opts, state: state diff --git a/lib/spawn/cluster/provisioner/spawn_task.ex b/lib/spawn/cluster/provisioner/spawn_task.ex index 487725c6..ed4be916 100644 --- a/lib/spawn/cluster/provisioner/spawn_task.ex +++ b/lib/spawn/cluster/provisioner/spawn_task.ex @@ -1,3 +1,3 @@ defmodule Spawn.Cluster.Provisioner.SpawnTask do - defstruct [:parent, :invocation, :opts, :state] + defstruct [:actor_name, :invocation, :opts, :state] end diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 33e011de..ef8e2678 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -73,9 +73,9 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do defp maybe_put_toleration(template, _topology), do: template - defp build_flame_pool(pod_template, %{"parentName" => name} = cfg, :prod) do + defp build_flame_pool(pod_template, %{"actorName" => name} = cfg, :prod) do pool_name = build_worker_pool_name(__MODULE__, name) - Logger.info("Create pool for parent Actor #{name}. Pool Name #{inspect(pool_name)}") + Logger.info("Create pool for Actor #{name}. Pool Name #{inspect(pool_name)}") opts = [ @@ -87,7 +87,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do {FLAME.Pool, opts} end - defp build_flame_pool(_pod_template, %{"parentName" => name} = cfg, _env) do + defp build_flame_pool(_pod_template, %{"actorName" => name} = cfg, _env) do pool_name = build_worker_pool_name(__MODULE__, name) Logger.info("Creating default pool with name #{inspect(pool_name)}") diff --git a/spawn_operator/spawn_operator/test/support/factory.ex b/spawn_operator/spawn_operator/test/support/factory.ex index 41f1c2fa..80b93205 100644 --- a/spawn_operator/spawn_operator/test/support/factory.ex +++ b/spawn_operator/spawn_operator/test/support/factory.ex @@ -65,7 +65,7 @@ defmodule SpawnOperator.FactoryTest do "image" => attrs[:host_image] || "eigr/spawn-test:latest", "taskActors" => [ %{ - "parentName" => "Jose", + "actorName" => "Jose", "topology" => %{ "nodeSelector" => %{ "gpu" => "false" From 7b9072fc7f3b49e4cadf14814f10bff8144a77f9 Mon Sep 17 00:00:00 2001 From: eliasdarruda Date: Mon, 30 Sep 2024 14:33:12 -0300 Subject: [PATCH 11/34] rename one_shoot to single_use --- examples/topology/host.yaml | 2 +- lib/spawn/cluster/provisioner_pool_supervisor.ex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/topology/host.yaml b/examples/topology/host.yaml index 79d626e4..fec84da5 100644 --- a/examples/topology/host.yaml +++ b/examples/topology/host.yaml @@ -50,7 +50,7 @@ spec: maxConcurrency: 100 bootTimeout: 30000 callTimeout: 30000 - oneShoot: "false" + singleUse: "false" idleShutdownAfter: 30000 topology: nodeSelector: diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index ef8e2678..13f6414a 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -124,7 +124,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do max_concurrency: Map.get(worker_pool_config, "maxConcurrency", 100), boot_timeout: Map.get(worker_pool_config, "bootTimeout", 30000), timeout: Map.get(worker_pool_config, "callTimeout", 30000), - single_use: Map.get(worker_pool_config, "oneShoot", "false"), + single_use: Map.get(worker_pool_config, "singleUse", "false"), idle_shutdown_after: Map.get(worker_pool_config, "idleShutdownAfter", 30000) ] end From b5923a8c6ce6a269360dd02a2aabc9a65f773588 Mon Sep 17 00:00:00 2001 From: eliasdarruda Date: Mon, 30 Sep 2024 14:39:19 -0300 Subject: [PATCH 12/34] one off instead of oneshoot --- examples/topology/host.yaml | 2 +- lib/spawn/cluster/provisioner_pool_supervisor.ex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/topology/host.yaml b/examples/topology/host.yaml index fec84da5..afe6f7ea 100644 --- a/examples/topology/host.yaml +++ b/examples/topology/host.yaml @@ -50,7 +50,7 @@ spec: maxConcurrency: 100 bootTimeout: 30000 callTimeout: 30000 - singleUse: "false" + oneOff: "false" idleShutdownAfter: 30000 topology: nodeSelector: diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 13f6414a..8df13656 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -124,7 +124,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do max_concurrency: Map.get(worker_pool_config, "maxConcurrency", 100), boot_timeout: Map.get(worker_pool_config, "bootTimeout", 30000), timeout: Map.get(worker_pool_config, "callTimeout", 30000), - single_use: Map.get(worker_pool_config, "singleUse", "false"), + single_use: Map.get(worker_pool_config, "oneOff", "false"), idle_shutdown_after: Map.get(worker_pool_config, "idleShutdownAfter", 30000) ] end From bcaae6979174c727d87fbb3d014ea2d38e3c02da Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 16:15:22 -0300 Subject: [PATCH 13/34] Create sa --- spawn_operator/spawn_operator/namespaced-roles.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spawn_operator/spawn_operator/namespaced-roles.yaml b/spawn_operator/spawn_operator/namespaced-roles.yaml index 4f781208..9b00132e 100644 --- a/spawn_operator/spawn_operator/namespaced-roles.yaml +++ b/spawn_operator/spawn_operator/namespaced-roles.yaml @@ -11,6 +11,16 @@ rules: - secrets verbs: - "*" + - apiGroups: + - "" + resources: + - "pods" + verbs: + - "create" + - "get" + - "list" + - "delete" + - "patch" --- apiVersion: v1 From 62b0505a68abc836ee35acfa870c8d5379ffeef8 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 17:28:58 -0300 Subject: [PATCH 14/34] Fix pattern matching --- lib/spawn/cluster/provisioner_pool_supervisor.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 8df13656..4d813afd 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -45,12 +45,14 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do end end - defp build_pod_template(%{"topology" => topology} = _cfg) do + defp build_pod_template(%{"topology" => topology} = cfg) do %{} |> maybe_put_node_selector(topology) |> maybe_put_toleration(topology) end + defp build_pod_template(cfg), do: %{} + defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do Map.merge(template, %{ "metadata" => %{ From 4c41ea25c717d698bfe4275e47320b08b06274a2 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 17:47:43 -0300 Subject: [PATCH 15/34] Update tests --- Makefile | 2 +- lib/spawn/cluster/provisioner_pool_supervisor.ex | 4 ++-- spawn_operator/spawn_operator/mix.lock | 2 ++ .../test/resources/actorhost/deployment_test.exs | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 3cd4d230..86b65b3a 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ build-all-images: #docker build --no-cache -f Dockerfile-elixir-example -t ${spawn-sdk-example-image} . test-spawn: - MIX_ENV=test SPAWN_PROXY_LOGGER_LEVEL=info SPAWN_PROXY_TASK_CONFIG="PMRHIYLTNNAWG5DPOJZSEOS3PMRHAYLSMVXHITTBNVSSEORCJJXXGZJCFQRHI33QN5WG6Z3ZEI5HWITON5SGKU3FNRSWG5DPOIRDU6ZCM5YHKIR2EJTGC3DTMURH27L5LV6Q====" PROXY_DATABASE_TYPE=native PROXY_DATABASE_PORT=3307 PROXY_DATABASE_POOL_SIZE=15 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test + MIX_ENV=test SPAWN_PROXY_LOGGER_LEVEL=info SPAWN_PROXY_TASK_CONFIG="PMRHIYLTNNAWG5DPOJZSEOS3PMRGCY3UN5ZE4YLNMURDUISKN5ZWKIRMEJ2G64DPNRXWO6JCHJ5SE3TPMRSVGZLMMVRXI33SEI5HWITHOB2SEORCMZQWY43FEJ6X27K5PU======" PROXY_DATABASE_TYPE=native PROXY_DATABASE_PORT=3307 PROXY_DATABASE_POOL_SIZE=15 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test test-statestores_mysql: cd spawn_statestores/statestores_mysql && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 4d813afd..223fe470 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -45,13 +45,13 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do end end - defp build_pod_template(%{"topology" => topology} = cfg) do + defp build_pod_template(%{"topology" => topology} = _cfg) do %{} |> maybe_put_node_selector(topology) |> maybe_put_toleration(topology) end - defp build_pod_template(cfg), do: %{} + defp build_pod_template(_cfg), do: %{} defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do Map.merge(template, %{ diff --git a/spawn_operator/spawn_operator/mix.lock b/spawn_operator/spawn_operator/mix.lock index cb1e4ae1..3ece5890 100644 --- a/spawn_operator/spawn_operator/mix.lock +++ b/spawn_operator/spawn_operator/mix.lock @@ -23,6 +23,8 @@ "elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"}, "exqlite": {:hex, :exqlite, "0.21.0", "8d06c60b3d6df42bb4cdeb4dce4bc804788e227cead7dc190c3ffaba50bffbb4", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "b177180bb2788b761ddd5949763640aef92ed06db80d70a1130b6bede180b45f"}, "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, + "flame": {:hex, :flame, "0.5.1", "339130ed9dff761efc1b2c001839e6d16aa9af291a1e155d8c14fa9b42c03caa", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, ">= 0.0.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "b09ac62b187f40fa7f959d6faca58aae0e575ff21435a8afd79727b8e5631085"}, + "flame_k8s_backend": {:hex, :flame_k8s_backend, "0.5.4", "4a14e5dd40ae5d26c47407e15acf81e322835fbbfb9e4b9c9e200ac5bf2cfaa8", [:mix], [{:flame, "~> 0.4.0 or ~> 0.5.0", [hex: :flame, repo: "hexpm", optional: false]}], "hexpm", "2a7973223e49d869d032e732425ae67283fa779d9c5e2f759d7f113473b86c42"}, "flow": {:hex, :flow, "1.2.4", "1dd58918287eb286656008777cb32714b5123d3855956f29aa141ebae456922d", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "874adde96368e71870f3510b91e35bc31652291858c86c0e75359cbdd35eb211"}, "gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"}, "gnat": {:hex, :gnat, "1.8.1", "f029e0bf2c073775524df939b4a4294a383199fe378d55476ca06d1717fee44e", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:cowlib, "~> 2.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:nkeys, "~> 0.2", [hex: :nkeys, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d4a9b4e90c5d457edab8161d8f2145655f1bf0abb50f2b492dd07187b7cd0376"}, diff --git a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs index d92020c1..1d92f13e 100644 --- a/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs +++ b/spawn_operator/spawn_operator/test/resources/actorhost/deployment_test.exs @@ -420,7 +420,7 @@ defmodule DeploymentTest do %{ "name" => "SPAWN_PROXY_TASK_CONFIG", "value" => - "PMRHIYLTNNAWG5DPOJZSEOS3PMRHAYLSMVXHITTBNVSSEORCJJXXGZJCFQRHI33QN5WG6Z3ZEI5HWITON5SGKU3FNRSWG5DPOIRDU6ZCM5YHKIR2EJTGC3DTMURH27L5LV6Q====" + "PMRHIYLTNNAWG5DPOJZSEOS3PMRGCY3UN5ZE4YLNMURDUISKN5ZWKIRMEJ2G64DPNRXWO6JCHJ5SE3TPMRSVGZLMMVRXI33SEI5HWITHOB2SEORCMZQWY43FEJ6X27K5PU======" } ], "envFrom" => [ From e18ec202fab4fa24da4173bd963788e713a9c4a6 Mon Sep 17 00:00:00 2001 From: eliasdarruda Date: Mon, 30 Sep 2024 18:33:53 -0300 Subject: [PATCH 16/34] build flame with right params --- .../cluster/provisioner_pool_supervisor.ex | 48 ++++++++++--------- test/actors/actors_test.exs | 2 +- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 223fe470..6576b822 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -21,9 +21,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do Enum.map(actor_configs, fn cfg -> Logger.info("Setup Task Actor with config: #{inspect(cfg)}") - cfg - |> build_pod_template() - |> build_flame_pool(cfg, env) + build_flame_pool(cfg, env) end) Supervisor.init(children, strategy: :one_for_one) @@ -45,51 +43,57 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do end end - defp build_pod_template(%{"topology" => topology} = _cfg) do - %{} + defp build_pod_template(%{"topology" => topology} = _cfg, template) do + template |> maybe_put_node_selector(topology) |> maybe_put_toleration(topology) end - defp build_pod_template(_cfg), do: %{} + defp build_pod_template(_cfg, template), do: %{} defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do - Map.merge(template, %{ - "metadata" => %{ - "labels" => %{"io.eigr.spawn/worker" => "true"} - }, - "spec" => %{"nodeSelector" => selector} - }) + new_label_map = + get_in(template, ["metadata", "labels"]) + |> Kernel.||(%{}) + |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) + + template + |> put_in(["metadata", "labels"], new_label_map) + |> put_in(["spec", "nodeSelector"], selector) end defp maybe_put_node_selector(template, _topology), do: template defp maybe_put_toleration(template, %{"tolerations" => toleration}) do - Map.merge(template, %{ - "metadata" => %{ - "labels" => %{"io.eigr.spawn/worker" => "true"} - }, - "spec" => %{"tolerations" => toleration} - }) + new_label_map = + get_in(template, ["metadata", "labels"]) + |> Kernel.||(%{}) + |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) + + template + |> put_in(["metadata", "labels"], new_label_map) + |> put_in(["spec", "tolerations"], toleration) end defp maybe_put_toleration(template, _topology), do: template - defp build_flame_pool(pod_template, %{"actorName" => name} = cfg, :prod) do + defp build_flame_pool(%{"actorName" => name} = cfg, :prod) do pool_name = build_worker_pool_name(__MODULE__, name) Logger.info("Create pool for Actor #{name}. Pool Name #{inspect(pool_name)}") opts = [ name: pool_name, - backend: {FLAMEK8sBackend, runner_pod_tpl: pod_template}, + backend: + {FLAMEK8sBackend, + runner_pod_tpl: fn current_manifest -> build_pod_template(cfg, current_manifest) end}, log: :debug ] ++ get_worker_pool_config(cfg) {FLAME.Pool, opts} end - defp build_flame_pool(_pod_template, %{"actorName" => name} = cfg, _env) do + defp build_flame_pool(%{"actorName" => name} = cfg, _env) do pool_name = build_worker_pool_name(__MODULE__, name) Logger.info("Creating default pool with name #{inspect(pool_name)}") @@ -103,7 +107,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do {FLAME.Pool, opts} end - defp build_flame_pool(_pod_template, cfg, _env) do + defp build_flame_pool(cfg, _env) do pool_name = Module.concat(__MODULE__, "Default") Logger.info("Creating default pool with name #{inspect(pool_name)}") diff --git a/test/actors/actors_test.exs b/test/actors/actors_test.exs index 4ba78a1d..845d731f 100644 --- a/test/actors/actors_test.exs +++ b/test/actors/actors_test.exs @@ -132,7 +132,7 @@ defmodule ActorsTest do mock_invoke_host_actor_with_ok_response(host_invoke_response) assert {:ok, %ActorInvocationResponse{actor_name: ^actor_name}} = - Actors.invoke(invoke_request) |> IO.inspect(label: "Remote response") + Actors.invoke(invoke_request) end @tag :skip From 6b1a9c1502810b018056dca869716e7eeb91a78b Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 30 Sep 2024 19:05:04 -0300 Subject: [PATCH 17/34] Add new envs --- .../lib/spawn_operator/k8s/proxy/deployment.ex | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index e24c87a8..dd5d4c98 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -14,6 +14,14 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do "name" => "NAMESPACE", "valueFrom" => %{"fieldRef" => %{"fieldPath" => "metadata.namespace"}} }, + %{ + "name" => "POD_NAME", + "valueFrom" => %{"fieldRef" => %{"fieldPath" => "metadata.name"}} + }, + %{ + "name" => "POD_NAMESPACE", + "valueFrom" => %{"fieldRef" => %{"fieldPath" => "metadata.namespace"}} + }, %{ "name" => "POD_IP", "valueFrom" => %{"fieldRef" => %{"fieldPath" => "status.podIP"}} From 228621ff4be102e44a44d176d30378b6a95a2aba Mon Sep 17 00:00:00 2001 From: Elias Dal Ben Date: Tue, 1 Oct 2024 00:44:17 -0300 Subject: [PATCH 18/34] Update provisioner_pool_supervisor.ex Signed-off-by: Elias Dal Ben --- lib/spawn/cluster/provisioner_pool_supervisor.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 6576b822..23d4f84f 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -49,7 +49,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do |> maybe_put_toleration(topology) end - defp build_pod_template(_cfg, template), do: %{} + defp build_pod_template(_cfg, template), do: template defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do new_label_map = From c35c27570ec9c85f0bd54f6abd11da2b61bdc472 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Tue, 1 Oct 2024 12:49:37 -0300 Subject: [PATCH 19/34] Refactor and fixes --- examples/security/acl/host.yaml | 2 +- .../security/authentication/basic/host.yaml | 2 +- .../security/authentication/jwt/host.yaml | 2 +- examples/simple/host-simple.yaml | 2 +- examples/simple/host.yaml | 2 +- .../cluster/provisioner_pool_supervisor.ex | 100 +++++++++--------- .../handler/actor_host_handler.ex | 4 +- 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/examples/security/acl/host.yaml b/examples/security/acl/host.yaml index f373197c..32ac82d0 100644 --- a/examples/security/acl/host.yaml +++ b/examples/security/acl/host.yaml @@ -9,7 +9,7 @@ metadata: spawn-eigr.io/sidecar-http-port: "9001" spawn-eigr.io/sidecar-pubsub-adapter: "nats" spawn-eigr.io/sidecar-pubsub-nats-hosts: "nats://spawn-nats:4222" - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.3" + spawn-eigr.io/sidecar-image-tag: "ghcr.io/eigr/spawn-proxy:1.4.3" spec: autoscaler: max: 3 diff --git a/examples/security/authentication/basic/host.yaml b/examples/security/authentication/basic/host.yaml index 139dfb40..871f9f9f 100644 --- a/examples/security/authentication/basic/host.yaml +++ b/examples/security/authentication/basic/host.yaml @@ -34,7 +34,7 @@ metadata: spawn-eigr.io/sidecar-http-port: "9001" spawn-eigr.io/sidecar-pubsub-adapter: "nats" spawn-eigr.io/sidecar-pubsub-nats-hosts: "nats://spawn-nats:4222" - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.3" + spawn-eigr.io/sidecar-image-tag: "ghcr.io/eigr/spawn-proxy:1.4.3" spec: autoscaler: max: 3 diff --git a/examples/security/authentication/jwt/host.yaml b/examples/security/authentication/jwt/host.yaml index 30cb87a8..72e6dba5 100644 --- a/examples/security/authentication/jwt/host.yaml +++ b/examples/security/authentication/jwt/host.yaml @@ -11,7 +11,7 @@ metadata: spawn-eigr.io/sidecar-http-port: "9001" spawn-eigr.io/sidecar-pubsub-adapter: "nats" spawn-eigr.io/sidecar-pubsub-nats-hosts: "nats://spawn-nats:4222" - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.3" + spawn-eigr.io/sidecar-image-tag: "ghcr.io/eigr/spawn-proxy:1.4.3" spec: autoscaler: max: 3 diff --git a/examples/simple/host-simple.yaml b/examples/simple/host-simple.yaml index 86ea46b6..713de3d8 100644 --- a/examples/simple/host-simple.yaml +++ b/examples/simple/host-simple.yaml @@ -14,7 +14,7 @@ metadata: # Optional. Here I`m using Nats Broker without authentication spawn-eigr.io/sidecar-pubsub-adapter: "nats" spawn-eigr.io/sidecar-pubsub-nats-hosts: "nats://spawn-nats:4222" - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.3" + spawn-eigr.io/sidecar-image-tag: "ghcr.io/eigr/spawn-proxy:1.4.3" spec: host: image: eigr/spawn-springboot-examples:0.5.3 # Mandatory diff --git a/examples/simple/host.yaml b/examples/simple/host.yaml index ac7ac1d2..6c066287 100644 --- a/examples/simple/host.yaml +++ b/examples/simple/host.yaml @@ -22,7 +22,7 @@ metadata: spawn-eigr.io/sidecar-mode: "sidecar" # Optional - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.3" + spawn-eigr.io/sidecar-image-tag: "ghcr.io/eigr/spawn-proxy:1.4.3" # Optional. Default 9001 spawn-eigr.io/sidecar-http-port: "9001" diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 23d4f84f..f3f67419 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -27,56 +27,6 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do Supervisor.init(children, strategy: :one_for_one) end - defp parse_config(""), do: [] - - defp parse_config(encoded_cfg) do - encoded_cfg - |> Base.decode32!() - |> Jason.decode!() - |> Map.get("taskActors", []) - end - - defp get_environment do - case System.get_env("MIX_ENV", "dev") do - "prod" -> :prod - env -> String.to_atom(env) - end - end - - defp build_pod_template(%{"topology" => topology} = _cfg, template) do - template - |> maybe_put_node_selector(topology) - |> maybe_put_toleration(topology) - end - - defp build_pod_template(_cfg, template), do: template - - defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do - new_label_map = - get_in(template, ["metadata", "labels"]) - |> Kernel.||(%{}) - |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) - - template - |> put_in(["metadata", "labels"], new_label_map) - |> put_in(["spec", "nodeSelector"], selector) - end - - defp maybe_put_node_selector(template, _topology), do: template - - defp maybe_put_toleration(template, %{"tolerations" => toleration}) do - new_label_map = - get_in(template, ["metadata", "labels"]) - |> Kernel.||(%{}) - |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) - - template - |> put_in(["metadata", "labels"], new_label_map) - |> put_in(["spec", "tolerations"], toleration) - end - - defp maybe_put_toleration(template, _topology), do: template - defp build_flame_pool(%{"actorName" => name} = cfg, :prod) do pool_name = build_worker_pool_name(__MODULE__, name) Logger.info("Create pool for Actor #{name}. Pool Name #{inspect(pool_name)}") @@ -134,4 +84,54 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do idle_shutdown_after: Map.get(worker_pool_config, "idleShutdownAfter", 30000) ] end + + defp build_pod_template(%{"topology" => topology} = _cfg, template) do + Map.delete(template, "resourceVersion") + |> maybe_put_node_selector(topology) + |> maybe_put_toleration(topology) + end + + defp build_pod_template(_cfg, template), do: Map.delete(template, "resourceVersion") + + defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do + new_label_map = + get_in(template, ["metadata", "labels"]) + |> Kernel.||(%{}) + |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) + + template + |> put_in(["metadata", "labels"], new_label_map) + |> put_in(["spec", "nodeSelector"], selector) + end + + defp maybe_put_node_selector(template, _topology), do: template + + defp maybe_put_toleration(template, %{"tolerations" => toleration}) do + new_label_map = + get_in(template, ["metadata", "labels"]) + |> Kernel.||(%{}) + |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) + + template + |> put_in(["metadata", "labels"], new_label_map) + |> put_in(["spec", "tolerations"], toleration) + end + + defp maybe_put_toleration(template, _topology), do: template + + defp parse_config(""), do: [] + + defp parse_config(encoded_cfg) do + encoded_cfg + |> Base.decode32!() + |> Jason.decode!() + |> Map.get("taskActors", []) + end + + defp get_environment do + case System.get_env("MIX_ENV", "dev") do + "prod" -> :prod + env -> String.to_atom(env) + end + end end diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/handler/actor_host_handler.ex b/spawn_operator/spawn_operator/lib/spawn_operator/handler/actor_host_handler.ex index 51e39f7e..734cea35 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/handler/actor_host_handler.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/handler/actor_host_handler.ex @@ -19,7 +19,7 @@ defmodule SpawnOperator.Handler.ActorHostHandler do spawn-eigr.io.sidecar.deploymentMode: "sidecar" # Optional - spawn-eigr.io.sidecar.containerImage: "docker.io/eigr/spawn-proxy" + spawn-eigr.io.sidecar.containerImage: "ghcr.io/eigr/spawn-proxy" # Optional spawn-eigr.io.sidecar.containerVersion: "1.4.3" @@ -82,7 +82,7 @@ defmodule SpawnOperator.Handler.ActorHostHandler do replicas: 1 # Optional. If negative number than autoscaling is enable host: # Mandatory - image: docker.io/eigr/spawn-springboot-examples:latest # Mandatory + image: ghcr.io/eigr/spawn-springboot-examples:latest # Mandatory embedded: false # Optional. Default false. True only when the SDK supports a native connection to the Spawn mesh network ports: - containerPort: 80 From 5ec5b6b938f017c1a6005237895453bc2fa8721a Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Tue, 1 Oct 2024 12:53:12 -0300 Subject: [PATCH 20/34] Remove resourceVersion --- lib/spawn/cluster/provisioner_pool_supervisor.ex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index f3f67419..506af97a 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -86,12 +86,13 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do end defp build_pod_template(%{"topology" => topology} = _cfg, template) do - Map.delete(template, "resourceVersion") + update_in(template["metadata"], &Map.drop(&1, ["resourceVersion"])) |> maybe_put_node_selector(topology) |> maybe_put_toleration(topology) end - defp build_pod_template(_cfg, template), do: Map.delete(template, "resourceVersion") + defp build_pod_template(_cfg, template), + do: update_in(template["metadata"], &Map.drop(&1, ["resourceVersion"])) defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do new_label_map = From eb8d74d7b28930328d619aa7ab2805ac8f8331b7 Mon Sep 17 00:00:00 2001 From: eliasdarruda Date: Tue, 1 Oct 2024 17:50:16 -0300 Subject: [PATCH 21/34] use app name sidecar --- lib/spawn/cluster/provisioner_pool_supervisor.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index 506af97a..c1464525 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -36,6 +36,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do name: pool_name, backend: {FLAMEK8sBackend, + app_container_name: "sidecar", runner_pod_tpl: fn current_manifest -> build_pod_template(cfg, current_manifest) end}, log: :debug ] ++ get_worker_pool_config(cfg) From 55b6b5d99b7770cb55b7a60048aff135701b5ce3 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Wed, 2 Oct 2024 13:20:06 -0300 Subject: [PATCH 22/34] Adjusts in flame to prevent node down --- Dockerfile-initializer | 8 ++------ config/prod.exs | 2 ++ lib/spawn/cluster/provisioner/scheduler.ex | 4 +++- .../lib/spawn_operator/k8s/proxy/deployment.ex | 6 +++++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Dockerfile-initializer b/Dockerfile-initializer index 903f3672..b3140100 100644 --- a/Dockerfile-initializer +++ b/Dockerfile-initializer @@ -13,15 +13,11 @@ RUN mix local.rebar --force \ && mix deps.get \ && mix release.init -# Overriden at runtime -ENV POD_IP="127.0.0.1" - # This will be the basename of node ENV RELEASE_NAME="spawn_initializer" -# This will be the full nodename -ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" - +# Disable Erlang Dist +ENV RELEASE_DISTRIBUTION=none RUN mix deps.get \ && mix release spawn_initializer diff --git a/config/prod.exs b/config/prod.exs index 1d5c1333..4537e2ca 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -3,3 +3,5 @@ import Config config :do_it, DoIt.Commfig, dirname: System.tmp_dir(), filename: "spawn_cli.json" + +config :flame, :terminator, failsafe_timer: :timer.seconds(30) diff --git a/lib/spawn/cluster/provisioner/scheduler.ex b/lib/spawn/cluster/provisioner/scheduler.ex index af6f8fb7..d62ebbf1 100644 --- a/lib/spawn/cluster/provisioner/scheduler.ex +++ b/lib/spawn/cluster/provisioner/scheduler.ex @@ -35,8 +35,10 @@ defmodule Spawn.Cluster.Provisioner.Scheduler do func ) when is_function(func) do + opts = Keyword.merge(opts, link: false) + build_worker_pool_name(ProvisionerPoolSupervisor, actor_name) - |> FLAME.call(fn -> func.({invocation, opts}, state) end) + |> FLAME.call(fn -> func.({invocation, opts}, state) end, opts) end end diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index dd5d4c98..f7f557a2 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -146,7 +146,11 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do "#{system}", "--to", "#{ns}" - ] + ], + "env" => %{ + "name" => "RELEASE_DISTRIBUTION", + "value" => "none" + } } ], "serviceAccountName" => "#{system}-sa" From 3aac953eafb01fc624857e0c1d071aa4369185f7 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Wed, 2 Oct 2024 17:38:42 -0300 Subject: [PATCH 23/34] Added option to override init container image --- spawn_operator/spawn_operator/lib/spawn_operator.ex | 6 ++++++ .../lib/spawn_operator/k8s/proxy/deployment.ex | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/spawn_operator/spawn_operator/lib/spawn_operator.ex b/spawn_operator/spawn_operator/lib/spawn_operator.ex index a7309af4..2fb158c5 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator.ex @@ -52,6 +52,12 @@ defmodule SpawnOperator do "spawn-eigr.io/sidecar-image-tag", "ghcr.io/eigr/spawn-proxy:1.4.3" ), + proxy_init_container_image_tag: + Map.get( + annotations, + "spawn-eigr.io/sidecar-init-container-image-tag", + "ghcr.io/eigr/spawn-initializer:1.4.3" + ), proxy_uds_enabled: Map.get(annotations, "spawn-eigr.io/sidecar-uds-enabled", "false"), proxy_uds_address: Map.get(annotations, "spawn-eigr.io/sidecar-uds-socket-path", "/var/run/spawn.sock"), diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index f7f557a2..06abe467 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -134,7 +134,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do "initContainers" => [ %{ "name" => "init-certificates", - "image" => "ghcr.io/eigr/spawn-initializer:1.4.3", + "image" => "#{annotations.proxy_init_container_image_tag}", "args" => [ "--environment", :prod, From 5a273951af5b2ae2a4737309ec7dd0e44fe3dbe9 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Thu, 3 Oct 2024 19:42:23 -0300 Subject: [PATCH 24/34] Fix typo --- config/prod.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/prod.exs b/config/prod.exs index 4537e2ca..43a4b038 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -4,4 +4,4 @@ config :do_it, DoIt.Commfig, dirname: System.tmp_dir(), filename: "spawn_cli.json" -config :flame, :terminator, failsafe_timer: :timer.seconds(30) +config :flame, :terminator, failsafe_timeout: :timer.seconds(30) From 0b528c5161c9a6a8f8321c2878a2473bd77855fe Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Thu, 3 Oct 2024 19:46:49 -0300 Subject: [PATCH 25/34] Fix runtime false for flame --- spawn_operator/spawn_operator/mix.exs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spawn_operator/spawn_operator/mix.exs b/spawn_operator/spawn_operator/mix.exs index 05cdff65..fa4ecd88 100644 --- a/spawn_operator/spawn_operator/mix.exs +++ b/spawn_operator/spawn_operator/mix.exs @@ -45,6 +45,8 @@ defmodule Operator.MixProject do {:bakeware, ">= 0.0.0", runtime: false}, {:bonny, "~> 1.1"}, {:castore, "~> 1.0"}, + {:flame, "~> 0.5", runtime: false}, + {:flame_k8s_backend, "~> 0.5", runtime: false}, {:spawn, path: "../../"} ] end From bf107f4d70a7cddf9955fe5ab852894b0ef63118 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 7 Oct 2024 20:00:16 -0300 Subject: [PATCH 26/34] fix. roles permissions --- examples/helloworld-ts/host.yaml | 20 +++++++++++++++++++ examples/helloworld-ts/system.yaml | 10 ++++++++++ .../spawn_operator/k8s/proxy/deployment.ex | 10 ++++++---- .../lib/spawn_operator/k8s/system/role.ex | 5 +++++ spawn_operator/spawn_operator/manifest.yaml | 8 ++++---- 5 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 examples/helloworld-ts/host.yaml create mode 100644 examples/helloworld-ts/system.yaml diff --git a/examples/helloworld-ts/host.yaml b/examples/helloworld-ts/host.yaml new file mode 100644 index 00000000..57939f5d --- /dev/null +++ b/examples/helloworld-ts/host.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: spawn-eigr.io/v1 +kind: ActorHost +metadata: + name: flame + namespace: default + annotations: + spawn-eigr.io/actor-system: spawn-system + spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.4-rc13" + spawn-eigr.io/sidecar-init-container-image-tag: "docker.io/eigr/spawn-initializer:1.4.4-rc13" +spec: + host: + image: eigr/helloworld:2 + taskActors: + - actorName: TaskActor + workerPool: + min: 20 + ports: + - name: http + containerPort: 8091 diff --git a/examples/helloworld-ts/system.yaml b/examples/helloworld-ts/system.yaml new file mode 100644 index 00000000..1ab851a7 --- /dev/null +++ b/examples/helloworld-ts/system.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: spawn-eigr.io/v1 +kind: ActorSystem +metadata: + name: spawn-system + namespace: default +spec: + statestore: + type: Native + credentialsSecretRef: mariadb-connection-secret diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index 06abe467..aba47cea 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -147,10 +147,12 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do "--to", "#{ns}" ], - "env" => %{ - "name" => "RELEASE_DISTRIBUTION", - "value" => "none" - } + "env" => [ + %{ + "name" => "RELEASE_DISTRIBUTION", + "value" => "none" + } + ] } ], "serviceAccountName" => "#{system}-sa" diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/role.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/role.ex index 34b6a269..825c268f 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/role.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/role.ex @@ -31,6 +31,11 @@ defmodule SpawnOperator.K8s.System.Role do "apiGroups" => [""], "resources" => ["configmaps", "secrets"], "verbs" => ["*"] + }, + %{ + "apiGroups" => [""], + "resources" => ["pods"], + "verbs" => ["create", "delete", "get", "list", "patch"] } ] } diff --git a/spawn_operator/spawn_operator/manifest.yaml b/spawn_operator/spawn_operator/manifest.yaml index dc821092..06551f91 100644 --- a/spawn_operator/spawn_operator/manifest.yaml +++ b/spawn_operator/spawn_operator/manifest.yaml @@ -38,7 +38,7 @@ spec: valueFrom: fieldRef: fieldPath: spec.serviceAccountName - image: ghcr.io/eigr/spawn-operator:1.4.3 + image: docker.io/eigr/spawn-operator:1.4.4-rc13 livenessProbe: failureThreshold: 3 httpGet: @@ -64,10 +64,10 @@ spec: timeoutSeconds: 5 resources: limits: - cpu: 200m - memory: 380Mi + cpu: 1 + memory: 1024Mi requests: - cpu: 200m + cpu: 10m memory: 380Mi securityContext: allowPrivilegeEscalation: false From a1f2e3da899a01768b9b8cd37a7eb09e6459c3df Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Thu, 10 Oct 2024 06:36:05 -0300 Subject: [PATCH 27/34] Update Flame terminator in prod.exs --- config/prod.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/prod.exs b/config/prod.exs index 43a4b038..23828411 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -4,4 +4,4 @@ config :do_it, DoIt.Commfig, dirname: System.tmp_dir(), filename: "spawn_cli.json" -config :flame, :terminator, failsafe_timeout: :timer.seconds(30) +config :flame, :terminator, failsafe_timeout: :timer.minuts(1) From 1913a16515e5e6903d56d0bb00b626b73bde066a Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Thu, 10 Oct 2024 06:37:21 -0300 Subject: [PATCH 28/34] Fix typo --- config/prod.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/prod.exs b/config/prod.exs index 23828411..441f9a2f 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -4,4 +4,4 @@ config :do_it, DoIt.Commfig, dirname: System.tmp_dir(), filename: "spawn_cli.json" -config :flame, :terminator, failsafe_timeout: :timer.minuts(1) +config :flame, :terminator, failsafe_timeout: :timer.minutes(1) From 367534a2740114dcd4f0cdb78654471378d4c9ae Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Thu, 10 Oct 2024 12:57:32 -0300 Subject: [PATCH 29/34] Some adjusts --- Dockerfile-activator-api | 2 +- Dockerfile-activator-kafka | 2 +- Dockerfile-activator-pubsub | 2 +- Dockerfile-activator-rabbitmq | 2 +- Dockerfile-activator-sqs | 2 +- Dockerfile-elixir-example | 2 +- Dockerfile-operator | 2 +- Dockerfile-proxy | 2 +- Makefile | 3 +- config/config.exs | 4 ++ config/prod.exs | 2 - examples/helloworld-ts/host.yaml | 8 ++-- lib/actors/actor/caller_consumer.ex | 2 +- lib/actors/actor/entity/entity.ex | 15 ++++++- lib/spawn/cluster/cluster_supervisor.ex | 2 +- .../cluster/provisioner_pool_supervisor.ex | 42 +++++++++++++++++-- mix.lock | 2 +- .../spawn_operator/k8s/proxy/deployment.ex | 39 +++++++++++++---- .../k8s/system/secret/actor_system_secret.ex | 2 +- spawn_operator/spawn_operator/manifest.yaml | 2 +- spawn_proxy/proxy/lib/proxy/application.ex | 3 ++ 21 files changed, 111 insertions(+), 31 deletions(-) diff --git a/Dockerfile-activator-api b/Dockerfile-activator-api index d155e7ba..8ab1884a 100644 --- a/Dockerfile-activator-api +++ b/Dockerfile-activator-api @@ -31,7 +31,7 @@ ENV RELEASE_NAME="activator_api" # This will be the full nodename ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" -RUN echo "-setcookie ${NODE_COOKIE}" >> ./rel/vm.args.eex +RUN echo "-setcookie ${RELEASE_COOKIE}" >> ./rel/vm.args.eex RUN cd spawn_activators/activator_api \ && mix deps.get \ diff --git a/Dockerfile-activator-kafka b/Dockerfile-activator-kafka index 23c515e4..28baafea 100644 --- a/Dockerfile-activator-kafka +++ b/Dockerfile-activator-kafka @@ -31,7 +31,7 @@ ENV RELEASE_NAME="activator_kafka" # This will be the full nodename ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" -RUN echo "-setcookie ${NODE_COOKIE}" >> ./rel/vm.args.eex +RUN echo "-setcookie ${RELEASE_COOKIE}" >> ./rel/vm.args.eex RUN cd spawn_activators/activator_kafka \ && mix deps.get \ diff --git a/Dockerfile-activator-pubsub b/Dockerfile-activator-pubsub index 4c076e9d..c79ed239 100644 --- a/Dockerfile-activator-pubsub +++ b/Dockerfile-activator-pubsub @@ -31,7 +31,7 @@ ENV RELEASE_NAME="activator_pubsub" # This will be the full nodename ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" -RUN echo "-setcookie ${NODE_COOKIE}" >> ./rel/vm.args.eex +RUN echo "-setcookie ${RELEASE_COOKIE}" >> ./rel/vm.args.eex RUN cd spawn_activators/activator_pubsub \ && mix deps.get \ diff --git a/Dockerfile-activator-rabbitmq b/Dockerfile-activator-rabbitmq index 59563eef..7776af9b 100644 --- a/Dockerfile-activator-rabbitmq +++ b/Dockerfile-activator-rabbitmq @@ -31,7 +31,7 @@ ENV RELEASE_NAME="activator_rabbitmq" # This will be the full nodename ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" -RUN echo "-setcookie ${NODE_COOKIE}" >> ./rel/vm.args.eex +RUN echo "-setcookie ${RELEASE_COOKIE}" >> ./rel/vm.args.eex RUN cd spawn_activators/activator_rabbitmq \ && mix deps.get \ diff --git a/Dockerfile-activator-sqs b/Dockerfile-activator-sqs index 8dec77d0..bea99014 100644 --- a/Dockerfile-activator-sqs +++ b/Dockerfile-activator-sqs @@ -31,7 +31,7 @@ ENV RELEASE_NAME="activator_sqs" # This will be the full nodename ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" -RUN echo "-setcookie ${NODE_COOKIE}" >> ./rel/vm.args.eex +RUN echo "-setcookie ${RELEASE_COOKIE}" >> ./rel/vm.args.eex RUN cd spawn_activators/activator_sqs \ && mix deps.get \ diff --git a/Dockerfile-elixir-example b/Dockerfile-elixir-example index b72f0895..1cba0eda 100644 --- a/Dockerfile-elixir-example +++ b/Dockerfile-elixir-example @@ -21,7 +21,7 @@ RUN mix local.rebar --force \ && mix release.init RUN echo "-name spawn_sdk_elixir@${HOSTNAME}" >> ./rel/vm.args.eex \ - && echo "-setcookie ${NODE_COOKIE}" >> ./rel/vm.args.eex + && echo "-setcookie ${RELEASE_COOKIE}" >> ./rel/vm.args.eex RUN cd spawn_sdk/spawn_sdk_example \ && mix deps.get \ diff --git a/Dockerfile-operator b/Dockerfile-operator index b1399e04..7750ab6f 100644 --- a/Dockerfile-operator +++ b/Dockerfile-operator @@ -31,7 +31,7 @@ ENV RELEASE_NAME="spawn_operator" # This will be the full nodename ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" -RUN echo "-setcookie ${NODE_COOKIE}" >> ./rel/vm.args.eex +RUN echo "-setcookie ${RELEASE_COOKIE}" >> ./rel/vm.args.eex RUN cd spawn_operator/spawn_operator \ && mix deps.get \ diff --git a/Dockerfile-proxy b/Dockerfile-proxy index b97bd317..19107e10 100644 --- a/Dockerfile-proxy +++ b/Dockerfile-proxy @@ -31,7 +31,7 @@ ENV RELEASE_NAME="proxy" # This will be the full nodename ENV RELEASE_NODE="${RELEASE_NAME}@${POD_IP}" -#RUN echo "-setcookie ${NODE_COOKIE}" >> ./priv/rel/vm.args.eex +#RUN echo "-setcookie ${RELEASE_COOKIE}" >> ./priv/rel/vm.args.eex RUN cd spawn_proxy/proxy \ && mix deps.get \ diff --git a/Makefile b/Makefile index 86b65b3a..a20ec395 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -version=1.4.3 +#version=1.4.3 +version=1.4.4-rc.22 registry=eigr CLUSTER_NAME=spawn-k8s diff --git a/config/config.exs b/config/config.exs index 78f09cd3..6b6751e1 100644 --- a/config/config.exs +++ b/config/config.exs @@ -4,6 +4,10 @@ config :do_it, DoIt.Commfig, dirname: System.tmp_dir(), filename: "spawn_cli.json" +config :flame, :terminator, + shutdown_timeout: :timer.minutes(2) + failsafe_timeout: :timer.minutes(1) + # config :spawn_statestores, Statestores.Vault, # json_library: Jason, # ciphers: [ diff --git a/config/prod.exs b/config/prod.exs index 43a4b038..1d5c1333 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -3,5 +3,3 @@ import Config config :do_it, DoIt.Commfig, dirname: System.tmp_dir(), filename: "spawn_cli.json" - -config :flame, :terminator, failsafe_timeout: :timer.seconds(30) diff --git a/examples/helloworld-ts/host.yaml b/examples/helloworld-ts/host.yaml index 57939f5d..3a70162d 100644 --- a/examples/helloworld-ts/host.yaml +++ b/examples/helloworld-ts/host.yaml @@ -6,15 +6,17 @@ metadata: namespace: default annotations: spawn-eigr.io/actor-system: spawn-system - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.4-rc13" - spawn-eigr.io/sidecar-init-container-image-tag: "docker.io/eigr/spawn-initializer:1.4.4-rc13" + spawn-eigr.io/sidecar-logger-level: debug + spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.4-rc.22" + spawn-eigr.io/sidecar-init-container-image-tag: "docker.io/eigr/spawn-initializer:1.4.4-rc.22" spec: + replicas: 2 host: image: eigr/helloworld:2 taskActors: - actorName: TaskActor workerPool: - min: 20 + min: 0 ports: - name: http containerPort: 8091 diff --git a/lib/actors/actor/caller_consumer.ex b/lib/actors/actor/caller_consumer.ex index 187ad3ce..fe4a36fd 100644 --- a/lib/actors/actor/caller_consumer.ex +++ b/lib/actors/actor/caller_consumer.ex @@ -515,7 +515,7 @@ defmodule Actors.Actor.CallerConsumer do # Instead of using Map.get/3, which performs a lookup twice, we use pattern matching timeout = case metadata["request-timeout"] do - nil -> 10_000 + nil -> 60_000 value -> value end diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index 2fa029a8..6d9248d6 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -79,7 +79,7 @@ defmodule Actors.Actor.Entity do alias Eigr.Functions.Protocol.State.Checkpoint alias Eigr.Functions.Protocol.State.Revision - alias Spawn.Cluster.Provisioner.Scheduler + alias Spawn.Cluster.Provisioner.Scheduler, as: FlameScheduler alias Spawn.Cluster.Provisioner.SpawnTask import Spawn.Utils.Common, only: [return_and_maybe_hibernate: 1] @@ -145,6 +145,8 @@ defmodule Actors.Actor.Entity do # The same applies to asynchronous calls. case state.actor.settings.kind do :TASK -> + opts = Keyword.merge(opts, timeout: :infinity) + task = %SpawnTask{ actor_name: state.actor.id.name, invocation: invocation, @@ -152,7 +154,16 @@ defmodule Actors.Actor.Entity do state: state } - Scheduler.schedule_and_invoke(task, &Invocation.invoke/2) + try do + resp = FlameScheduler.schedule_and_invoke(task, &Invocation.invoke/2) + + IO.inspect(resp, + label: "FlameScheduler invoke response ---------------------------" + ) + catch + error -> + IO.inspect(error, label: "Error during Flame Scheduler invocation ---------") + end _ -> Invocation.invoke({invocation, opts}, state) diff --git a/lib/spawn/cluster/cluster_supervisor.ex b/lib/spawn/cluster/cluster_supervisor.ex index 1a18ecf2..6df2beb7 100644 --- a/lib/spawn/cluster/cluster_supervisor.ex +++ b/lib/spawn/cluster/cluster_supervisor.ex @@ -97,7 +97,7 @@ defmodule Spawn.Cluster.ClusterSupervisor do strategy: Elixir.Cluster.Strategy.Kubernetes.DNS, config: [ service: Config.get(:proxy_headless_service), - application_name: "spawn", + application_name: "proxy", polling_interval: Config.get(:proxy_cluster_polling_interval) ] ] diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index c1464525..dcc4eefb 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -79,10 +79,11 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do min: Map.get(worker_pool_config, "min", 0), max: Map.get(worker_pool_config, "max", 10), max_concurrency: Map.get(worker_pool_config, "maxConcurrency", 100), - boot_timeout: Map.get(worker_pool_config, "bootTimeout", 30000), - timeout: Map.get(worker_pool_config, "callTimeout", 30000), single_use: Map.get(worker_pool_config, "oneOff", "false"), - idle_shutdown_after: Map.get(worker_pool_config, "idleShutdownAfter", 30000) + timeout: Map.get(worker_pool_config, "callTimeout", :infinity), + boot_timeout: Map.get(worker_pool_config, "bootTimeout", :timer.minutes(3)), + idle_shutdown_after: Map.get(worker_pool_config, "idleShutdownAfter", :timer.minutes(1)), + track_resources: true ] end @@ -90,6 +91,41 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do update_in(template["metadata"], &Map.drop(&1, ["resourceVersion"])) |> maybe_put_node_selector(topology) |> maybe_put_toleration(topology) + + # |> update_in(["containers", Access.at(0)], fn container -> + # container + # |> Map.put_new("env", []) + # |> Map.update!("env", fn env -> + # [ + # %{ + # "name" => "POD_NAME", + # "valueFrom" => %{"fieldRef" => %{"fieldPath" => "metadata.name"}} + # }, + # %{ + # "name" => "POD_IP", + # "valueFrom" => %{"fieldRef" => %{"fieldPath" => "status.podIP"}} + # }, + # %{ + # "name" => "POD_NAMESPACE", + # "valueFrom" => %{"fieldRef" => %{"fieldPath" => "metadata.namespace"}} + # }, + # %{"name" => "FLAME_PARENT", "value" => encoded_parent} + # | Enum.reject( + # env, + # &(&1["name"] in ["FLAME_PARENT", "POD_NAME", "POD_NAMESPACE", "POD_IP"]) + # ) + # ] + # |> put_new_env("NODE_COOKIE", Node.get_cookie()) + # end) + end + + defp put_new_env(env, _name, :nocookie), do: env + + defp put_new_env(env, name, value) do + case get_in(env, [Access.filter(&(&1["name"] == name))]) do + [] -> [%{"name" => name, "value" => value} | env] + _ -> env + end end defp build_pod_template(_cfg, template), diff --git a/mix.lock b/mix.lock index b8c17330..4459b78a 100644 --- a/mix.lock +++ b/mix.lock @@ -28,7 +28,7 @@ "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, "flame": {:hex, :flame, "0.5.1", "339130ed9dff761efc1b2c001839e6d16aa9af291a1e155d8c14fa9b42c03caa", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, ">= 0.0.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "b09ac62b187f40fa7f959d6faca58aae0e575ff21435a8afd79727b8e5631085"}, - "flame_k8s_backend": {:hex, :flame_k8s_backend, "0.5.4", "4a14e5dd40ae5d26c47407e15acf81e322835fbbfb9e4b9c9e200ac5bf2cfaa8", [:mix], [{:flame, "~> 0.4.0 or ~> 0.5.0", [hex: :flame, repo: "hexpm", optional: false]}], "hexpm", "2a7973223e49d869d032e732425ae67283fa779d9c5e2f759d7f113473b86c42"}, + "flame_k8s_backend": {:hex, :flame_k8s_backend, "0.5.6", "91b9e2816366ed23020e05fead38a992b86230b112b6d4be2ef2776d586aea99", [:mix], [{:flame, "~> 0.4.0 or ~> 0.5.0", [hex: :flame, repo: "hexpm", optional: false]}], "hexpm", "e403571de233045a858ba9efcfcc0cfc68a5aa1e8c48b16428cdbad2f8dff72d"}, "flow": {:hex, :flow, "1.2.4", "1dd58918287eb286656008777cb32714b5123d3855956f29aa141ebae456922d", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "874adde96368e71870f3510b91e35bc31652291858c86c0e75359cbdd35eb211"}, "gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"}, "gnat": {:hex, :gnat, "1.8.5", "31d7f75dcca90164b2d811bcbc1a94b9049a0f586c219594687d6bd9493043a5", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:cowlib, "~> 2.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:nkeys, "~> 0.2", [hex: :nkeys, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5e62a8f6f02a12191a9ca79ea94f5899db7ec32a0e8554cac9930196298e8cb6"}, diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index aba47cea..834e26f5 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -8,7 +8,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do @default_actor_host_function_env [ %{ "name" => "RELEASE_NAME", - "value" => "spawn" + "value" => "proxy" }, %{ "name" => "NAMESPACE", @@ -98,7 +98,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do "spec" => %{ "replicas" => replicas, "selector" => %{ - "matchLabels" => %{"app" => name, "actor-system" => system} + "matchLabels" => %{"actor-system" => system} }, "strategy" => %{ "type" => "RollingUpdate", @@ -135,6 +135,9 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do %{ "name" => "init-certificates", "image" => "#{annotations.proxy_init_container_image_tag}", + "env" => [ + %{"containerPort" => 4369, "name" => "epmd"} + ], "args" => [ "--environment", :prod, @@ -216,12 +219,23 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do defp get_containers(true, system, name, host_params, annotations, task_actors_config) do actor_host_function_image = Map.get(host_params, "image") + updated_default_envs = + @default_actor_host_function_env ++ + [ + %{ + "name" => "RELEASE_COOKIE", + "valueFrom" => %{ + "secretKeyRef" => %{"name" => "#{system}-secret", "key" => "RELEASE_COOKIE"} + } + } + ] + actor_host_function_envs = if is_nil(task_actors_config) || List.first(Map.values(task_actors_config)) == %{} do - Map.get(host_params, "env", []) ++ @default_actor_host_function_env + Map.get(host_params, "env", []) ++ updated_default_envs else Map.get(host_params, "env", []) ++ - @default_actor_host_function_env ++ + updated_default_envs ++ build_task_env(task_actors_config) end @@ -268,9 +282,20 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do defp get_containers(false, system, name, host_params, annotations, task_actors_config) do actor_host_function_image = Map.get(host_params, "image") + updated_default_envs = + @default_actor_host_function_env ++ + [ + %{ + "name" => "RELEASE_COOKIE", + "valueFrom" => %{ + "secretKeyRef" => %{"name" => "#{system}-secret", "key" => "RELEASE_COOKIE"} + } + } + ] + actor_host_function_envs = Map.get(host_params, "env", []) ++ - @default_actor_host_function_env + updated_default_envs actor_host_function_resources = Map.get(host_params, "resources", @default_actor_host_resources) @@ -284,9 +309,9 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do envs = if is_nil(task_actors_config) || List.first(Map.values(task_actors_config)) == %{} do - @default_actor_host_function_env + updated_default_envs else - @default_actor_host_function_env ++ build_task_env(task_actors_config) + updated_default_envs ++ build_task_env(task_actors_config) end proxy_container = diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/secret/actor_system_secret.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/secret/actor_system_secret.ex index 22ace7b8..6e740710 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/secret/actor_system_secret.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/system/secret/actor_system_secret.ex @@ -96,7 +96,7 @@ defmodule SpawnOperator.K8s.System.Secret.ActorSystemSecret do cluster_heartbeat = "240000" |> Base.encode64() %{ - "NODE_COOKIE" => cookie, + "RELEASE_COOKIE" => cookie, "PROXY_ACTOR_SYSTEM_NAME" => Base.encode64(system), "PROXY_CLUSTER_POLLING" => cluster_poolling, "PROXY_CLUSTER_STRATEGY" => cluster_strategy, diff --git a/spawn_operator/spawn_operator/manifest.yaml b/spawn_operator/spawn_operator/manifest.yaml index 06551f91..4e5a2a03 100644 --- a/spawn_operator/spawn_operator/manifest.yaml +++ b/spawn_operator/spawn_operator/manifest.yaml @@ -38,7 +38,7 @@ spec: valueFrom: fieldRef: fieldPath: spec.serviceAccountName - image: docker.io/eigr/spawn-operator:1.4.4-rc13 + image: docker.io/eigr/spawn-operator:1.4.4-rc.22 livenessProbe: failureThreshold: 3 httpGet: diff --git a/spawn_proxy/proxy/lib/proxy/application.ex b/spawn_proxy/proxy/lib/proxy/application.ex index a6d9ad7f..fe1ca815 100644 --- a/spawn_proxy/proxy/lib/proxy/application.ex +++ b/spawn_proxy/proxy/lib/proxy/application.ex @@ -17,6 +17,9 @@ defmodule Proxy.Application do OpentelemetryEcto.setup([:spawn_statestores, :repo]) Config.load() + System.get_env("RELEASE_COOKIE") + |> IO.inspect(label: "Application Cookie ------------------------------") + Logger.configure(level: Config.get(:logger_level)) children = [ From 70c9295132b2d81483fa83a029a5333733eb43d0 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 11 Oct 2024 03:33:00 -0300 Subject: [PATCH 30/34] Fixes flame invocation and handle invocation results --- Makefile | 2 +- config/config.exs | 5 +- examples/helloworld-ts/host.yaml | 4 +- lib/actors/actor/entity/entity.ex | 24 ++- .../cluster/provisioner_pool_supervisor.ex | 151 ++++++++---------- .../spawn_operator/k8s/proxy/deployment.ex | 2 +- spawn_operator/spawn_operator/manifest.yaml | 2 +- spawn_proxy/proxy/lib/proxy/application.ex | 2 - 8 files changed, 89 insertions(+), 103 deletions(-) diff --git a/Makefile b/Makefile index a20ec395..f8d847e7 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ #version=1.4.3 -version=1.4.4-rc.22 +version=1.4.4-rc.35 registry=eigr CLUSTER_NAME=spawn-k8s diff --git a/config/config.exs b/config/config.exs index 6b6751e1..1b2a855f 100644 --- a/config/config.exs +++ b/config/config.exs @@ -5,8 +5,9 @@ config :do_it, DoIt.Commfig, filename: "spawn_cli.json" config :flame, :terminator, - shutdown_timeout: :timer.minutes(2) - failsafe_timeout: :timer.minutes(1) + shutdown_timeout: :timer.minutes(3), + failsafe_timeout: :timer.minutes(1), + log: :debug # config :spawn_statestores, Statestores.Vault, # json_library: Jason, diff --git a/examples/helloworld-ts/host.yaml b/examples/helloworld-ts/host.yaml index 3a70162d..7fe26938 100644 --- a/examples/helloworld-ts/host.yaml +++ b/examples/helloworld-ts/host.yaml @@ -7,8 +7,8 @@ metadata: annotations: spawn-eigr.io/actor-system: spawn-system spawn-eigr.io/sidecar-logger-level: debug - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.4-rc.22" - spawn-eigr.io/sidecar-init-container-image-tag: "docker.io/eigr/spawn-initializer:1.4.4-rc.22" + spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.4-rc.35" + spawn-eigr.io/sidecar-init-container-image-tag: "docker.io/eigr/spawn-initializer:1.4.4-rc.35" spec: replicas: 2 host: diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index 6d9248d6..7b343558 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -76,6 +76,8 @@ defmodule Actors.Actor.Entity do alias Eigr.Functions.Protocol.Actors.Healthcheck.HealthCheckReply alias Eigr.Functions.Protocol.Actors.Healthcheck.Status, as: HealthcheckStatus + alias Eigr.Functions.Protocol.ActorInvocationResponse + alias Eigr.Functions.Protocol.State.Checkpoint alias Eigr.Functions.Protocol.State.Revision @@ -154,15 +156,21 @@ defmodule Actors.Actor.Entity do state: state } - try do - resp = FlameScheduler.schedule_and_invoke(task, &Invocation.invoke/2) + FlameScheduler.schedule_and_invoke(task, &Invocation.invoke/2) + |> IO.inspect(label: "Remoting Scheduler raw response") + |> case do + {:reply, {:ok, %ActorInvocationResponse{}} = resp, %EntityState{} = _state, _signal} = + payload -> + Logger.debug("Remoting Scheduler response for invocation: #{inspect(resp)}") + + payload + + unexpect -> + Logger.error( + "Error during Remoting Scheduler invocation. Details: #{inspect(unexpect)}" + ) - IO.inspect(resp, - label: "FlameScheduler invoke response ---------------------------" - ) - catch - error -> - IO.inspect(error, label: "Error during Flame Scheduler invocation ---------") + unexpect end _ -> diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index dcc4eefb..a6570bc9 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -20,57 +20,33 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do children = Enum.map(actor_configs, fn cfg -> Logger.info("Setup Task Actor with config: #{inspect(cfg)}") - build_flame_pool(cfg, env) end) Supervisor.init(children, strategy: :one_for_one) end - defp build_flame_pool(%{"actorName" => name} = cfg, :prod) do + defp build_flame_pool(%{"actorName" => name} = cfg, env) do pool_name = build_worker_pool_name(__MODULE__, name) - Logger.info("Create pool for Actor #{name}. Pool Name #{inspect(pool_name)}") + Logger.info("Creating pool for Actor #{name}. Pool Name: #{inspect(pool_name)}") opts = [ name: pool_name, - backend: - {FLAMEK8sBackend, - app_container_name: "sidecar", - runner_pod_tpl: fn current_manifest -> build_pod_template(cfg, current_manifest) end}, + backend: pool_backend(cfg, env), log: :debug ] ++ get_worker_pool_config(cfg) {FLAME.Pool, opts} end - defp build_flame_pool(%{"actorName" => name} = cfg, _env) do - pool_name = build_worker_pool_name(__MODULE__, name) - Logger.info("Creating default pool with name #{inspect(pool_name)}") - - opts = - [ - name: pool_name, - backend: FLAME.LocalBackend, - log: :debug - ] ++ get_worker_pool_config(cfg) - - {FLAME.Pool, opts} + defp pool_backend(cfg, :prod) do + {FLAMEK8sBackend, + app_container_name: "sidecar", + runner_pod_tpl: fn current_manifest -> build_pod_template(cfg, current_manifest) end} end - defp build_flame_pool(cfg, _env) do - pool_name = Module.concat(__MODULE__, "Default") - Logger.info("Creating default pool with name #{inspect(pool_name)}") - - opts = - [ - name: pool_name, - backend: FLAME.LocalBackend, - log: :debug - ] ++ get_worker_pool_config(cfg) - - {FLAME.Pool, opts} - end + defp pool_backend(_, _env), do: FLAME.LocalBackend defp get_worker_pool_config(cfg) do worker_pool_config = Map.get(cfg, "workerPool", %{}) @@ -87,76 +63,79 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do ] end - defp build_pod_template(%{"topology" => topology} = _cfg, template) do - update_in(template["metadata"], &Map.drop(&1, ["resourceVersion"])) - |> maybe_put_node_selector(topology) - |> maybe_put_toleration(topology) - - # |> update_in(["containers", Access.at(0)], fn container -> - # container - # |> Map.put_new("env", []) - # |> Map.update!("env", fn env -> - # [ - # %{ - # "name" => "POD_NAME", - # "valueFrom" => %{"fieldRef" => %{"fieldPath" => "metadata.name"}} - # }, - # %{ - # "name" => "POD_IP", - # "valueFrom" => %{"fieldRef" => %{"fieldPath" => "status.podIP"}} - # }, - # %{ - # "name" => "POD_NAMESPACE", - # "valueFrom" => %{"fieldRef" => %{"fieldPath" => "metadata.namespace"}} - # }, - # %{"name" => "FLAME_PARENT", "value" => encoded_parent} - # | Enum.reject( - # env, - # &(&1["name"] in ["FLAME_PARENT", "POD_NAME", "POD_NAMESPACE", "POD_IP"]) - # ) - # ] - # |> put_new_env("NODE_COOKIE", Node.get_cookie()) - # end) + defp build_pod_template(cfg, template) do + Logger.debug("Building pod template...") + + template + |> update_pod_metadata() + |> update_pod_spec() + |> remove_probes_from_containers() + |> maybe_put_node_selector(cfg) + |> maybe_put_toleration(cfg) end - defp put_new_env(env, _name, :nocookie), do: env + defp update_pod_metadata(template) do + target_metadata = %{ + "name" => "target-pod", + "namespace" => Access.get(template, "metadata")["namespace"], + "annotations" => %{ + "prometheus.io/path" => "/metrics", + "prometheus.io/port" => "9001", + "prometheus.io/scrape" => "true" + } + } + + put_in(template["metadata"], target_metadata) + end - defp put_new_env(env, name, value) do - case get_in(env, [Access.filter(&(&1["name"] == name))]) do - [] -> [%{"name" => name, "value" => value} | env] - _ -> env - end + defp update_pod_spec(template) do + spec = template["spec"] + + target_spec = %{ + "initContainers" => spec["initContainers"], + "containers" => spec["containers"], + "volumes" => spec["volumes"], + "serviceAccount" => spec["serviceAccount"], + "serviceAccountName" => spec["serviceAccountName"], + "terminationGracePeriodSeconds" => spec["terminationGracePeriodSeconds"], + "restartPolicy" => "Never" + } + + put_in(template["spec"], target_spec) end - defp build_pod_template(_cfg, template), - do: update_in(template["metadata"], &Map.drop(&1, ["resourceVersion"])) + defp remove_probes_from_containers(template) do + updated_containers = + template["spec"]["containers"] + |> Enum.map(&Map.drop(&1, ["readinessProbe", "livenessProbe"])) - defp maybe_put_node_selector(template, %{"nodeSelector" => selector}) do - new_label_map = - get_in(template, ["metadata", "labels"]) - |> Kernel.||(%{}) - |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) + put_in(template["spec"]["containers"], updated_containers) + end - template - |> put_in(["metadata", "labels"], new_label_map) - |> put_in(["spec", "nodeSelector"], selector) + defp maybe_put_node_selector(template, %{"topology" => topology}) do + update_metadata_with_labels(template) + |> put_in(["spec", "nodeSelector"], topology["nodeSelector"]) + end + + defp maybe_put_node_selector(template, _cfg), do: template + + defp maybe_put_toleration(template, %{"topology" => topology}) do + update_metadata_with_labels(template) + |> put_in(["spec", "tolerations"], topology["tolerations"]) end - defp maybe_put_node_selector(template, _topology), do: template + defp maybe_put_toleration(template, _cfg), do: template - defp maybe_put_toleration(template, %{"tolerations" => toleration}) do + defp update_metadata_with_labels(template) do new_label_map = - get_in(template, ["metadata", "labels"]) + template + |> get_in(["metadata", "labels"]) |> Kernel.||(%{}) |> Map.merge(%{"io.eigr.spawn/worker" => "true"}) - template - |> put_in(["metadata", "labels"], new_label_map) - |> put_in(["spec", "tolerations"], toleration) + put_in(template["metadata"]["labels"], new_label_map) end - defp maybe_put_toleration(template, _topology), do: template - defp parse_config(""), do: [] defp parse_config(encoded_cfg) do diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index 834e26f5..017ba542 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -295,7 +295,7 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do actor_host_function_envs = Map.get(host_params, "env", []) ++ - updated_default_envs + updated_default_envs actor_host_function_resources = Map.get(host_params, "resources", @default_actor_host_resources) diff --git a/spawn_operator/spawn_operator/manifest.yaml b/spawn_operator/spawn_operator/manifest.yaml index 4e5a2a03..daa35e18 100644 --- a/spawn_operator/spawn_operator/manifest.yaml +++ b/spawn_operator/spawn_operator/manifest.yaml @@ -38,7 +38,7 @@ spec: valueFrom: fieldRef: fieldPath: spec.serviceAccountName - image: docker.io/eigr/spawn-operator:1.4.4-rc.22 + image: docker.io/eigr/spawn-operator:1.4.4-rc.35 livenessProbe: failureThreshold: 3 httpGet: diff --git a/spawn_proxy/proxy/lib/proxy/application.ex b/spawn_proxy/proxy/lib/proxy/application.ex index fe1ca815..cc8dbd43 100644 --- a/spawn_proxy/proxy/lib/proxy/application.ex +++ b/spawn_proxy/proxy/lib/proxy/application.ex @@ -17,8 +17,6 @@ defmodule Proxy.Application do OpentelemetryEcto.setup([:spawn_statestores, :repo]) Config.load() - System.get_env("RELEASE_COOKIE") - |> IO.inspect(label: "Application Cookie ------------------------------") Logger.configure(level: Config.get(:logger_level)) From e51b2f0b04161a82c5439038af426ca28769a374 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 11 Oct 2024 20:40:01 -0300 Subject: [PATCH 31/34] Handle response on parent node for task actors --- Makefile | 4 +- examples/helloworld-ts/host.yaml | 4 +- lib/actors/actor/entity/entity.ex | 156 +++++++++++++----- lib/actors/actor/entity/invocation.ex | 51 +++--- .../cluster/provisioner_pool_supervisor.ex | 2 +- .../spawn_operator/k8s/proxy/deployment.ex | 1 - spawn_operator/spawn_operator/manifest.yaml | 2 +- 7 files changed, 146 insertions(+), 74 deletions(-) diff --git a/Makefile b/Makefile index f8d847e7..f6439807 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ #version=1.4.3 -version=1.4.4-rc.35 +version=1.4.4-rc.38 registry=eigr CLUSTER_NAME=spawn-k8s @@ -96,7 +96,7 @@ test-operator: cd spawn_operator/spawn_operator && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_DATABASE_TYPE=mysql PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test test-proxy: - cd spawn_proxy/proxy && MIX_ENV=test mix deps.get && MIX_ENV=test SPAWN_PROXY_LOGGER_LEVEL=debug PROXY_DATABASE_TYPE=mariadb PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test + cd spawn_proxy/proxy && MIX_ENV=test mix deps.get && MIX_ENV=test SPAWN_PROXY_LOGGER_LEVEL=debug PROXY_DATABASE_TYPE=native PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test run-benchmark: cd spawn_sdk/spawn_sdk_example && mix deps.get && SPAWN_PROXY_LOGGER_LEVEL=info PROXY_CLUSTER_STRATEGY=gossip PROXY_DATABASE_TYPE=mariadb PROXY_DATABASE_PORT=3307 PROXY_DATABASE_POOL_SIZE=50 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= iex --name spawn@127.0.0.1 -S mix run benchmark.exs diff --git a/examples/helloworld-ts/host.yaml b/examples/helloworld-ts/host.yaml index 7fe26938..aba75d0a 100644 --- a/examples/helloworld-ts/host.yaml +++ b/examples/helloworld-ts/host.yaml @@ -7,8 +7,8 @@ metadata: annotations: spawn-eigr.io/actor-system: spawn-system spawn-eigr.io/sidecar-logger-level: debug - spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.4-rc.35" - spawn-eigr.io/sidecar-init-container-image-tag: "docker.io/eigr/spawn-initializer:1.4.4-rc.35" + spawn-eigr.io/sidecar-image-tag: "docker.io/eigr/spawn-proxy:1.4.4-rc.38" + spawn-eigr.io/sidecar-init-container-image-tag: "docker.io/eigr/spawn-initializer:1.4.4-rc.38" spec: replicas: 2 host: diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index 7b343558..0db1d271 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -128,61 +128,131 @@ defmodule Actors.Actor.Entity do |> return_and_maybe_hibernate() end + @doc """ + Handles different types of incoming `call` actions for an actor process. + + This function is responsible for processing actions sent to the actor. It distinguishes between invocation requests + and other default actions. The main action handled is the `:invocation_request`, which includes logic for task-based + actors and synchronous execution. + + ### Parameters: + - `action`: Represents the action to be handled by the actor. It can be a tuple of `{:invocation_request, invocation, opts}` + or other actions. + - `from`: The caller process that made the request, usually a tuple containing the PID and a reference. + - `state`: The current state of the actor, typically passed in a packed format and unpacked at the start of the function. + + ### Action Handling: + - `{:invocation_request, invocation, opts}`: + - If the actor is of kind `:TASK`, the function schedules the task execution remotely using `FlameScheduler.schedule_and_invoke/2`. + - For non-task actors, the function directly invokes the action using `Invocation.invoke/2`. + - Default actions are delegated to `do_handle_defaults/3`. + + ### Return Value: + The function returns a packed response, which is either the result of an invocation or the default action handling. + The response is further processed by `parse_packed_response/1`. + + ### Workflow: + 1. The actor's state is unpacked via `EntityState.unpack/1`. + 2. Based on the `action`: + - For `{:invocation_request, invocation, opts}`, the function checks if the actor is of kind `:TASK`: + - If true, the invocation is handled remotely with the remote task scheduler (`FlameScheduler`), ensuring proper remote invocation while maintaining local state consistency. + - Otherwise, the action is invoked locally. + - For other actions, `do_handle_defaults/3` is called to manage additional behaviors. + 3. The final response is returned as a packed structure after being processed by `parse_packed_response/1`. + + ### See Also: + - `handle_invocation_request/4` + - `schedule_task_invocation/3` + - `FlameScheduler.schedule_and_invoke/2` + - `Invocation.invoke/2` + """ @impl true def handle_call(action, from, state) do state = EntityState.unpack(state) case action do {:invocation_request, invocation, opts} -> - opts = Keyword.merge(opts, from_pid: from) - # Check if actor is Task and call Invocation.invoke in remote POD. - # This code is executed here to ensure that a real instance of the target actor is present locally. - # On the remote node, the code will run with communication to the ActorHost happening locally via the - # sidecar. However, the return of the call will be directed to this process, - # allowing the local state to be updated, even though the execution occurred remotely. - - # In synchronous calls, this also ensures that the deactivate timeout will not be impacted. - # If this process fails, it is likely that Scheduler via Flame will terminate the remote process. - # We still need to perform more tests to understand how this will affect the system. - # The same applies to asynchronous calls. - case state.actor.settings.kind do - :TASK -> - opts = Keyword.merge(opts, timeout: :infinity) - - task = %SpawnTask{ - actor_name: state.actor.id.name, - invocation: invocation, - opts: opts, - state: state - } - - FlameScheduler.schedule_and_invoke(task, &Invocation.invoke/2) - |> IO.inspect(label: "Remoting Scheduler raw response") - |> case do - {:reply, {:ok, %ActorInvocationResponse{}} = resp, %EntityState{} = _state, _signal} = - payload -> - Logger.debug("Remoting Scheduler response for invocation: #{inspect(resp)}") - - payload - - unexpect -> - Logger.error( - "Error during Remoting Scheduler invocation. Details: #{inspect(unexpect)}" - ) - - unexpect - end - - _ -> - Invocation.invoke({invocation, opts}, state) - end + handle_invocation_request(invocation, opts, from, state) - action -> + _ -> do_handle_defaults(action, from, state) end |> parse_packed_response() end + defp handle_invocation_request(invocation, opts, from, state) do + opts = Keyword.merge(opts, from_pid: from) + + case state.actor.settings.kind do + :TASK -> + schedule_task_invocation(invocation, opts, state) + + _ -> + Invocation.invoke({invocation, opts}, state) + end + end + + defp schedule_task_invocation(invocation, opts, state) do + task_opts = Keyword.merge(opts, timeout: :infinity) + + %SpawnTask{ + actor_name: state.actor.id.name, + invocation: invocation, + opts: task_opts, + state: state + } + |> FlameScheduler.schedule_and_invoke(&Invocation.invoke/2) + |> then(fn + {:ok, source_request, dest_response, updated_state, source_opts} -> + # Handle response here ensures that the full response behavior will be given by the Actor + # that initiated the remote call and not the target POD, + # which could cause unwanted side effects. + # For this works we need to disable track_resources: false + Invocation.handle_response(source_request, dest_response, updated_state, source_opts) + + res -> + res + end) + |> handle_scheduler_response() + end + + defp handle_scheduler_response( + {:reply, {:ok, %ActorInvocationResponse{} = resp}, %EntityState{} = _state} = + payload + ) do + Logger.debug("Remoting Scheduler response for invocation: #{inspect(resp)}") + payload + end + + defp handle_scheduler_response( + {:reply, {:ok, %ActorInvocationResponse{} = resp}, %EntityState{} = _state, _signal} = + payload + ) do + Logger.debug("Remoting Scheduler response for invocation: #{inspect(resp)}") + payload + end + + defp handle_scheduler_response( + {:noreply, %EntityState{} = _state} = + payload + ) do + Logger.debug("Remoting Scheduler response for invocation ok") + payload + end + + defp handle_scheduler_response( + {:noreply, %EntityState{} = _state, _signal} = + payload + ) do + Logger.debug("Remoting Scheduler response for invocation ok") + payload + end + + defp handle_scheduler_response(another) do + Logger.error("Error during Remoting Scheduler invocation. Details: #{inspect(another)}") + another + end + defp do_handle_defaults(action, from, state) do case action do :get_state -> diff --git a/lib/actors/actor/entity/invocation.ex b/lib/actors/actor/entity/invocation.ex index dde4b78d..ade6b740 100644 --- a/lib/actors/actor/entity/invocation.ex +++ b/lib/actors/actor/entity/invocation.ex @@ -285,6 +285,28 @@ defmodule Actors.Actor.Entity.Invocation do end end + def handle_response( + request, + %ActorInvocationResponse{checkpoint: checkpoint} = response, + %EntityState{ + revision: revision + } = state, + opts + ) do + response = + case do_response(request, response, state, opts) do + :noreply -> + {:noreply, state} + |> return_and_maybe_hibernate() + + response -> + {:reply, {:ok, response}, state} + |> return_and_maybe_hibernate() + end + + response_checkpoint(response, checkpoint, revision, state) + end + defp is_authorized?(invocation, actions, timers) do acl_manager = get_acl_manager() @@ -315,10 +337,13 @@ defmodule Actors.Actor.Entity.Invocation do Tracer.with_span "invoke-host" do case interface.invoke_host(request, state, @default_actions) do {:ok, response, new_state} -> - handle_response(request, response, new_state, opts) + {:ok, request, response, new_state, opts} + + # handle_response(request, response, new_state, opts) {:error, reason, new_state} -> - {:reply, {:error, reason}, new_state} |> return_and_maybe_hibernate() + {:reply, {:error, reason}, new_state} + |> return_and_maybe_hibernate() end end end @@ -366,28 +391,6 @@ defmodule Actors.Actor.Entity.Invocation do } end - defp handle_response( - request, - %ActorInvocationResponse{checkpoint: checkpoint} = response, - %EntityState{ - revision: revision - } = state, - opts - ) do - response = - case do_response(request, response, state, opts) do - :noreply -> - {:noreply, state} - |> return_and_maybe_hibernate() - - response -> - {:reply, {:ok, response}, state} - |> return_and_maybe_hibernate() - end - - response_checkpoint(response, checkpoint, revision, state) - end - defp response_checkpoint(response, checkpoint, revision, state) do if checkpoint do Lifecycle.checkpoint(revision, state) diff --git a/lib/spawn/cluster/provisioner_pool_supervisor.ex b/lib/spawn/cluster/provisioner_pool_supervisor.ex index a6570bc9..6a66bf8c 100644 --- a/lib/spawn/cluster/provisioner_pool_supervisor.ex +++ b/lib/spawn/cluster/provisioner_pool_supervisor.ex @@ -59,7 +59,7 @@ defmodule Spawn.Cluster.ProvisionerPoolSupervisor do timeout: Map.get(worker_pool_config, "callTimeout", :infinity), boot_timeout: Map.get(worker_pool_config, "bootTimeout", :timer.minutes(3)), idle_shutdown_after: Map.get(worker_pool_config, "idleShutdownAfter", :timer.minutes(1)), - track_resources: true + track_resources: false ] end diff --git a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex index 017ba542..813a7992 100644 --- a/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex +++ b/spawn_operator/spawn_operator/lib/spawn_operator/k8s/proxy/deployment.ex @@ -79,7 +79,6 @@ defmodule SpawnOperator.K8s.Proxy.Deployment do ) do host_params = Map.get(params, "host") task_actors_config = %{"taskActors" => Map.get(host_params, "taskActors", %{})} - IO.inspect(task_actors_config, label: "Config ------------------------") topology = Map.get(params, "topology", %{}) replicas = max(1, Map.get(params, "replicas", @default_actor_host_function_replicas)) diff --git a/spawn_operator/spawn_operator/manifest.yaml b/spawn_operator/spawn_operator/manifest.yaml index daa35e18..553d4e1c 100644 --- a/spawn_operator/spawn_operator/manifest.yaml +++ b/spawn_operator/spawn_operator/manifest.yaml @@ -38,7 +38,7 @@ spec: valueFrom: fieldRef: fieldPath: spec.serviceAccountName - image: docker.io/eigr/spawn-operator:1.4.4-rc.35 + image: docker.io/eigr/spawn-operator:1.4.4-rc.38 livenessProbe: failureThreshold: 3 httpGet: From 576a63b5181b9772edf2599bb74437e9d6bd4b66 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Tue, 15 Oct 2024 00:34:41 -0300 Subject: [PATCH 32/34] Add cast invoke --- lib/actors/actor/entity/entity.ex | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index 0db1d271..d0532044 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -404,9 +404,12 @@ defmodule Actors.Actor.Entity do case action do {:invocation_request, invocation, opts} -> - Invocation.invoke({invocation, opts}, state) + handle_invocation_request(invocation, opts, from, state) |> reply_to_noreply() + #Invocation.invoke({invocation, opts}, state) + #|> reply_to_noreply() + action -> do_handle_cast(action, state) end From c32a17db9abde2474b422d5c6be656c5569d2f34 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Tue, 15 Oct 2024 15:13:54 -0300 Subject: [PATCH 33/34] Enabled async invocations using flame --- lib/actors/actor/entity/entity.ex | 17 ++++++++++++----- lib/spawn/cluster/provisioner/scheduler.ex | 13 ++++++++++++- lib/spawn/cluster/provisioner/spawn_task.ex | 2 +- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/actors/actor/entity/entity.ex b/lib/actors/actor/entity/entity.ex index d0532044..a3d137e4 100644 --- a/lib/actors/actor/entity/entity.ex +++ b/lib/actors/actor/entity/entity.ex @@ -189,17 +189,26 @@ defmodule Actors.Actor.Entity do _ -> Invocation.invoke({invocation, opts}, state) + |> then(fn + {:ok, source_request, dest_response, updated_state, source_opts} -> + Invocation.handle_response(source_request, dest_response, updated_state, source_opts) + + res -> + res + end) end end defp schedule_task_invocation(invocation, opts, state) do task_opts = Keyword.merge(opts, timeout: :infinity) + request_type = Keyword.get(opts, :async, false) %SpawnTask{ actor_name: state.actor.id.name, invocation: invocation, opts: task_opts, - state: state + state: state, + async: request_type } |> FlameScheduler.schedule_and_invoke(&Invocation.invoke/2) |> then(fn @@ -404,12 +413,10 @@ defmodule Actors.Actor.Entity do case action do {:invocation_request, invocation, opts} -> - handle_invocation_request(invocation, opts, from, state) + opts = Keyword.merge(opts, async: true) + handle_invocation_request(invocation, opts, nil, state) |> reply_to_noreply() - #Invocation.invoke({invocation, opts}, state) - #|> reply_to_noreply() - action -> do_handle_cast(action, state) end diff --git a/lib/spawn/cluster/provisioner/scheduler.ex b/lib/spawn/cluster/provisioner/scheduler.ex index d62ebbf1..79eb1544 100644 --- a/lib/spawn/cluster/provisioner/scheduler.ex +++ b/lib/spawn/cluster/provisioner/scheduler.ex @@ -31,7 +31,7 @@ defmodule Spawn.Cluster.Provisioner.Scheduler do The result of executing the provided function within the context of the actor provisioning system. """ def execute( - %SpawnTask{actor_name: actor_name, invocation: invocation, opts: opts, state: state}, + %SpawnTask{actor_name: actor_name, invocation: invocation, opts: opts, state: state, async: false}, func ) when is_function(func) do @@ -40,6 +40,17 @@ defmodule Spawn.Cluster.Provisioner.Scheduler do build_worker_pool_name(ProvisionerPoolSupervisor, actor_name) |> FLAME.call(fn -> func.({invocation, opts}, state) end, opts) end + + def execute( + %SpawnTask{actor_name: actor_name, invocation: invocation, opts: opts, state: state, async: true}, + func + ) + when is_function(func) do + opts = Keyword.merge(opts, link: false) + + build_worker_pool_name(ProvisionerPoolSupervisor, actor_name) + |> FLAME.cast(fn -> func.({invocation, opts}, state) end, opts) + end end @doc """ diff --git a/lib/spawn/cluster/provisioner/spawn_task.ex b/lib/spawn/cluster/provisioner/spawn_task.ex index ed4be916..3944d737 100644 --- a/lib/spawn/cluster/provisioner/spawn_task.ex +++ b/lib/spawn/cluster/provisioner/spawn_task.ex @@ -1,3 +1,3 @@ defmodule Spawn.Cluster.Provisioner.SpawnTask do - defstruct [:actor_name, :invocation, :opts, :state] + defstruct [:actor_name, :invocation, :opts, :state, :async] end From 437e4a9a3d6e66e9bbc924dddd657a464ecd600d Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Tue, 15 Oct 2024 16:53:35 -0300 Subject: [PATCH 34/34] Add task actor in spawn elixir sdk --- Makefile | 15 ++----- lib/spawn/utils/common.ex | 9 ++++ .../spawn_sdk/lib/system/spawn_system.ex | 2 + spawn_sdk/spawn_sdk/test/actor/actor_test.exs | 45 +++++++++++++++++++ 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index f6439807..28e74698 100644 --- a/Makefile +++ b/Makefile @@ -68,32 +68,23 @@ build-all-images: test-spawn: MIX_ENV=test SPAWN_PROXY_LOGGER_LEVEL=info SPAWN_PROXY_TASK_CONFIG="PMRHIYLTNNAWG5DPOJZSEOS3PMRGCY3UN5ZE4YLNMURDUISKN5ZWKIRMEJ2G64DPNRXWO6JCHJ5SE3TPMRSVGZLMMVRXI33SEI5HWITHOB2SEORCMZQWY43FEJ6X27K5PU======" PROXY_DATABASE_TYPE=native PROXY_DATABASE_PORT=3307 PROXY_DATABASE_POOL_SIZE=15 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test -test-statestores_mysql: - cd spawn_statestores/statestores_mysql && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test - test-statestores_mariadb: cd spawn_statestores/statestores_mariadb && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_DATABASE_TYPE=mariadb PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test test-statestores_postgres: cd spawn_statestores/statestores_postgres && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 PROXY_DATABASE_USERNAME=postgres PROXY_DATABASE_SECRET=postgres SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test -test-statestores_mssql: - cd spawn_statestores/statestores_mssql && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test - -test-statestores_sqlite: - cd spawn_statestores/statestores_sqlite && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test - test-statestores_native: cd spawn_statestores/statestores_native && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test test-spawn-sdk: - cd spawn_sdk/spawn_sdk && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_DATABASE_TYPE=mariadb PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= PROXY_ACTOR_SYSTEM_NAME=spawn-system elixir --name spawn_test@127.0.0.1 -S mix test + cd spawn_sdk/spawn_sdk && MIX_ENV=test mix deps.get && MIX_ENV=test SPAWN_PROXY_USE_DEFAULT_FLAME_POOL=true PROXY_DATABASE_TYPE=native PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= PROXY_ACTOR_SYSTEM_NAME=spawn-system elixir --name spawn_test@127.0.0.1 -S mix test test-invoke-backpressure: - cd spawn_sdk/spawn_sdk && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_DATABASE_TYPE=mariadb PROXY_DATABASE_POOL_SIZE=50 PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= PROXY_ACTOR_SYSTEM_NAME=spawn-system elixir --name spawn_test@127.0.0.1 -S mix test ./test/actor/actor_test.exs --only parallel:true + cd spawn_sdk/spawn_sdk && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_DATABASE_TYPE=native PROXY_DATABASE_POOL_SIZE=50 PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= PROXY_ACTOR_SYSTEM_NAME=spawn-system elixir --name spawn_test@127.0.0.1 -S mix test ./test/actor/actor_test.exs --only parallel:true test-operator: - cd spawn_operator/spawn_operator && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_DATABASE_TYPE=mysql PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test + cd spawn_operator/spawn_operator && MIX_ENV=test mix deps.get && MIX_ENV=test PROXY_DATABASE_TYPE=native PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test test-proxy: cd spawn_proxy/proxy && MIX_ENV=test mix deps.get && MIX_ENV=test SPAWN_PROXY_LOGGER_LEVEL=debug PROXY_DATABASE_TYPE=native PROXY_DATABASE_PORT=3307 PROXY_CLUSTER_STRATEGY=gossip PROXY_HTTP_PORT=9005 SPAWN_STATESTORE_KEY=3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE= elixir --name spawn@127.0.0.1 -S mix test diff --git a/lib/spawn/utils/common.ex b/lib/spawn/utils/common.ex index 5b96182c..0876a63d 100644 --- a/lib/spawn/utils/common.ex +++ b/lib/spawn/utils/common.ex @@ -6,9 +6,18 @@ defmodule Spawn.Utils.Common do alias Eigr.Functions.Protocol.Actors.ActorId def build_worker_pool_name(module, parent) do + System.get_env("SPAWN_PROXY_USE_DEFAULT_FLAME_POOL", "false") + |> do_build_worker_pool_name(module, parent) + end + + defp do_build_worker_pool_name("false", module, parent) do Module.concat(module, String.upcase(parent)) end + defp do_build_worker_pool_name("true", module, _parent) do + Module.concat(module, "default") + end + @spec actor_host_hash() :: integer() def actor_host_hash() do system = Config.get(:actor_system_name) diff --git a/spawn_sdk/spawn_sdk/lib/system/spawn_system.ex b/spawn_sdk/spawn_sdk/lib/system/spawn_system.ex index 4c16792a..420ced8f 100644 --- a/spawn_sdk/spawn_sdk/lib/system/spawn_system.ex +++ b/spawn_sdk/spawn_sdk/lib/system/spawn_system.ex @@ -566,6 +566,8 @@ defmodule SpawnSdk.System.SpawnSystem do def decode_kind(:singleton), do: :NAMED def decode_kind(:named), do: :NAMED def decode_kind(:NAMED), do: :NAMED + def decode_kind(:TASK), do: :TASK + def decode_kind(:task), do: :TASK def decode_kind(:pooled), do: :POOLED def decode_kind(:POOLED), do: :POOLED def decode_kind(_), do: :UNKNOW_KIND diff --git a/spawn_sdk/spawn_sdk/test/actor/actor_test.exs b/spawn_sdk/spawn_sdk/test/actor/actor_test.exs index 6e43d64a..036ca9a0 100644 --- a/spawn_sdk/spawn_sdk/test/actor/actor_test.exs +++ b/spawn_sdk/spawn_sdk/test/actor/actor_test.exs @@ -3,6 +3,32 @@ defmodule Actor.ActorTest do require Logger + alias Eigr.Spawn.Actor.{MyMessageRequest, MyMessageResponse} + + defmodule Actor.TaskActor do + use SpawnSdk.Actor, + name: "task_actor_ref", + kind: :task, + stateful: true, + state_type: Eigr.Spawn.Actor.MyState, + tags: [{"foo", "none"}, {"bar", "unchanged"}] + + defact init(_) do + Value.noreply_state!(%{value: 0}) + end + + action("sum", fn %Context{} = ctx, %MyMessageRequest{id: id, data: data} -> + current_state = ctx.state + new_state = current_state + 1 + + response = %MyMessageResponse{id: id, data: data} + result = %Value{state: new_state, value: response} + + result + |> Value.noreply!() + end) + end + defmodule Actor.MyActor do use SpawnSdk.Actor, name: "my_actor_ref", @@ -225,6 +251,7 @@ defmodule Actor.ActorTest do Actor.PooledActor, Actor.JsonActor, Actor.BroadcastActor, + Actor.TaskActor, Actor.TimerActor ] } @@ -271,6 +298,24 @@ defmodule Actor.ActorTest do end end + describe "invoke task actors" do + test "simple invoke task actor", ctx do + system = ctx.system + actor_name = "task_actor_ref" + + SpawnSdk.invoke(actor_name, + action: "sum", + system: system, + payload: %{value: 999} + ) + + assert SpawnSdk.invoke(actor_name, + action: "getState", + system: system + ) == {:ok, %{value: 999}} + end + end + describe "invoke json actor" do test "simple default function call returning only map without payload", ctx do system = ctx.system