From b6514bb2e47e393544d8e404b26bf45549e2d0d8 Mon Sep 17 00:00:00 2001 From: Cassie Coyle Date: Mon, 2 Oct 2023 13:04:03 -0500 Subject: [PATCH] Updated actor configuration (#914) * add actor type config Signed-off-by: MregXN * add actor reentrancy config Signed-off-by: MregXN * add actor type config and object serializer Signed-off-by: MregXN * add tests Signed-off-by: MregXN * modify tests Signed-off-by: MregXN * fix some typos Signed-off-by: MregXN * add a test Signed-off-by: MregXN * rm actor reentrancy Signed-off-by: Cassandra Coyle * rm reentrancy from tests Signed-off-by: Cassandra Coyle * fix merge issues due to juint5 refactor being merged and update assertions to conform Signed-off-by: Cassandra Coyle * hopefully fixed merge weirdness Signed-off-by: Cassandra Coyle --------- Signed-off-by: MregXN Signed-off-by: Cassandra Coyle Signed-off-by: Cassie Coyle Co-authored-by: MregXN Co-authored-by: MregXN <46479059+MregXN@users.noreply.github.com> Co-authored-by: Artur Souza --- .../actors/runtime/ActorObjectSerializer.java | 33 ++++ .../actors/runtime/ActorRuntimeConfig.java | 25 +++ .../dapr/actors/runtime/ActorTypeConfig.java | 164 ++++++++++++++++++ .../dapr/actors/runtime/ActorRuntimeTest.java | 54 +++++- 4 files changed, 271 insertions(+), 5 deletions(-) create mode 100644 sdk-actors/src/main/java/io/dapr/actors/runtime/ActorTypeConfig.java diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java index 82ee62009..131c3521c 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java @@ -146,6 +146,39 @@ public class ActorObjectSerializer extends ObjectSerializer { if (config.getRemindersStoragePartitions() != null) { generator.writeNumberField("remindersStoragePartitions", config.getRemindersStoragePartitions()); } + if (!config.getActorTypeConfigs().isEmpty()) { + + generator.writeArrayFieldStart("entitiesConfig"); + for (ActorTypeConfig actorTypeConfig : config.getActorTypeConfigs()) { + generator.writeStartObject(); + if (actorTypeConfig.getActorTypeName() != null) { + generator.writeArrayFieldStart("entities"); + generator.writeString(actorTypeConfig.getActorTypeName()); + generator.writeEndArray(); + } + if (actorTypeConfig.getActorIdleTimeout() != null) { + generator.writeStringField("actorIdleTimeout", + DurationUtils.convertDurationToDaprFormat(actorTypeConfig.getActorIdleTimeout())); + } + if (actorTypeConfig.getActorScanInterval() != null) { + generator.writeStringField("actorScanInterval", + DurationUtils.convertDurationToDaprFormat(actorTypeConfig.getActorScanInterval())); + } + if (actorTypeConfig.getDrainOngoingCallTimeout() != null) { + generator.writeStringField("drainOngoingCallTimeout", + DurationUtils.convertDurationToDaprFormat(actorTypeConfig.getDrainOngoingCallTimeout())); + } + if (actorTypeConfig.getDrainBalancedActors() != null) { + generator.writeBooleanField("drainBalancedActors", actorTypeConfig.getDrainBalancedActors()); + } + if (actorTypeConfig.getRemindersStoragePartitions() != null) { + generator.writeNumberField("remindersStoragePartitions", actorTypeConfig.getRemindersStoragePartitions()); + } + + generator.writeEndObject(); + } + generator.writeEndArray(); + } generator.writeEndObject(); generator.close(); writer.flush(); diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntimeConfig.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntimeConfig.java index bfadb38cb..7e42d49ae 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntimeConfig.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntimeConfig.java @@ -36,6 +36,8 @@ public class ActorRuntimeConfig { private volatile Integer remindersStoragePartitions; + private volatile List actorTypeConfigs = new CopyOnWriteArrayList<>(); + /** * Instantiates a new config for the Actor Runtime. */ @@ -166,4 +168,27 @@ public class ActorRuntimeConfig { return this; } + /** + * Adds a actor type config to the list of actors type configs. + * + * @param actorTypeName Actor type that was registered. + * @return This instance. + */ + ActorRuntimeConfig addActorTypeConfig(ActorTypeConfig config) { + if (config == null) { + throw new IllegalArgumentException("Add actor type config failed."); + } + + this.actorTypeConfigs.add(config); + return this; + } + + /** + * Gets the list of registered actor types. + * + * @return List of registered actor types. + */ + Collection getActorTypeConfigs() { + return Collections.unmodifiableCollection(actorTypeConfigs); + } } diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorTypeConfig.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorTypeConfig.java new file mode 100644 index 000000000..ce3d2d524 --- /dev/null +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorTypeConfig.java @@ -0,0 +1,164 @@ +/* + * Copyright 2021 The Dapr Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and +limitations under the License. +*/ + +package io.dapr.actors.runtime; + +import java.time.Duration; + +/** + * Represents the configuration for the Actor Type. + */ +public class ActorTypeConfig { + + private String actorTypeName; + + private volatile Duration actorIdleTimeout; + + private volatile Duration actorScanInterval; + + private volatile Duration drainOngoingCallTimeout; + + private volatile Boolean drainBalancedActors; + + private volatile Integer remindersStoragePartitions; + + /** + * Instantiates a new config for the Actor Runtime. + */ + ActorTypeConfig() { + } + + /** + * Sets registered actors name. + * + * @param actorTypeName Actor type that was registered. + * @return This instance. + */ + ActorTypeConfig setActorTypeName(String actorTypeName) { + if (actorTypeName == null) { + throw new IllegalArgumentException("Registered actor must have a type name."); + } + + this.actorTypeName = actorTypeName; + return this; + } + + /** + * Gets registered actor types name. + * + * @return Registered actor types name. + */ + String getActorTypeName() { + return this.actorTypeName; + } + + /** + * Gets the duration for Actors' timeout. + * + * @return Duration for Actors' timeout. + */ + public Duration getActorIdleTimeout() { + return this.actorIdleTimeout; + } + + /** + * Sets the duration for Actors' timeout. + * + * @param actorIdleTimeout Duration for Actors' timeout. + * @return This instance. + */ + public ActorTypeConfig setActorIdleTimeout(Duration actorIdleTimeout) { + this.actorIdleTimeout = actorIdleTimeout; + return this; + } + + /** + * Gets the duration to scan for Actors. + * + * @return The duration to scan for Actors. + */ + public Duration getActorScanInterval() { + return this.actorScanInterval; + } + + /** + * Sets the duration to scan for Actors. + * + * @param actorScanInterval The duration to scan for Actors. + * @return This instance. + */ + public ActorTypeConfig setActorScanInterval(Duration actorScanInterval) { + this.actorScanInterval = actorScanInterval; + return this; + } + + /** + * Gets the timeout to drain ongoing calls. + * + * @return The timeout to drain ongoing calls. + */ + public Duration getDrainOngoingCallTimeout() { + return this.drainOngoingCallTimeout; + } + + /** + * Sets the timeout to drain ongoing calls. + * + * @param drainOngoingCallTimeout The timeout to drain ongoing calls. + * @return This instance. + */ + public ActorTypeConfig setDrainOngoingCallTimeout(Duration drainOngoingCallTimeout) { + this.drainOngoingCallTimeout = drainOngoingCallTimeout; + return this; + } + + /** + * Gets whether balanced actors should be drained. + * + * @return Whether balanced actors should be drained. + */ + public Boolean getDrainBalancedActors() { + return this.drainBalancedActors; + } + + /** + * Sets whether balanced actors should be drained. + * + * @param drainBalancedActors Whether balanced actors should be drained. + * @return This instance. + */ + public ActorTypeConfig setDrainBalancedActors(Boolean drainBalancedActors) { + this.drainBalancedActors = drainBalancedActors; + return this; + } + + /** + * Gets the number of storage partitions for Actor reminders. + * + * @return The number of Actor reminder storage partitions. + */ + public Integer getRemindersStoragePartitions() { + return this.remindersStoragePartitions; + } + + /** + * Sets the number of storage partitions for Actor reminders. + * + * @param remindersStoragePartitions The number of storage partitions for Actor reminders. + * @return This instance. + */ + public ActorTypeConfig setRemindersStoragePartitions(Integer remindersStoragePartitions) { + this.remindersStoragePartitions = remindersStoragePartitions; + return this; + } +} diff --git a/sdk-actors/src/test/java/io/dapr/actors/runtime/ActorRuntimeTest.java b/sdk-actors/src/test/java/io/dapr/actors/runtime/ActorRuntimeTest.java index 62132c9f2..49167116f 100644 --- a/sdk-actors/src/test/java/io/dapr/actors/runtime/ActorRuntimeTest.java +++ b/sdk-actors/src/test/java/io/dapr/actors/runtime/ActorRuntimeTest.java @@ -104,11 +104,11 @@ public class ActorRuntimeTest { @BeforeAll public static void beforeAll() throws Exception { constructor = - (Constructor) Arrays.stream(ActorRuntime.class.getDeclaredConstructors()) - .filter(c -> c.getParameters().length == 2).map(c -> { - c.setAccessible(true); - return c; - }).findFirst().get(); + (Constructor) Arrays.stream(ActorRuntime.class.getDeclaredConstructors()) + .filter(c -> c.getParameters().length == 2).map(c -> { + c.setAccessible(true); + return c; + }).findFirst().get(); } @BeforeEach @@ -161,6 +161,50 @@ public class ActorRuntimeTest { new String(this.runtime.serializeConfig())); } + @Test + public void addActorTypeConfig() throws Exception { + ActorTypeConfig actorTypeConfig1 = new ActorTypeConfig(); + actorTypeConfig1.setActorTypeName("actor1"); + actorTypeConfig1.setActorIdleTimeout(Duration.ofSeconds(123)); + actorTypeConfig1.setActorScanInterval(Duration.ofSeconds(123)); + actorTypeConfig1.setDrainOngoingCallTimeout(Duration.ofSeconds(123)); + actorTypeConfig1.setDrainBalancedActors(true); + actorTypeConfig1.setRemindersStoragePartitions(1); + this.runtime.getConfig().addActorTypeConfig(actorTypeConfig1); + this.runtime.getConfig().addRegisteredActorType("actor1"); + + ActorTypeConfig actorTypeConfig2 = new ActorTypeConfig(); + actorTypeConfig2.setActorTypeName("actor2"); + actorTypeConfig2.setActorIdleTimeout(Duration.ofSeconds(123)); + actorTypeConfig2.setActorScanInterval(Duration.ofSeconds(123)); + actorTypeConfig2.setDrainOngoingCallTimeout(Duration.ofSeconds(123)); + actorTypeConfig2.setDrainBalancedActors(false); + actorTypeConfig2.setRemindersStoragePartitions(2); + this.runtime.getConfig().addActorTypeConfig(actorTypeConfig2); + this.runtime.getConfig().addRegisteredActorType("actor2"); + + Assertions.assertEquals( + "{\"entities\":[\"actor1\",\"actor2\"],\"entitiesConfig\":[{\"entities\":[\"actor1\"],\"actorIdleTimeout\":\"0h2m3s0ms\",\"actorScanInterval\":\"0h2m3s0ms\",\"drainOngoingCallTimeout\":\"0h2m3s0ms\",\"drainBalancedActors\":true,\"remindersStoragePartitions\":1},{\"entities\":[\"actor2\"],\"actorIdleTimeout\":\"0h2m3s0ms\",\"actorScanInterval\":\"0h2m3s0ms\",\"drainOngoingCallTimeout\":\"0h2m3s0ms\",\"drainBalancedActors\":false,\"remindersStoragePartitions\":2}]}", + new String(this.runtime.serializeConfig()) + ); + } + + @Test + public void addNullActorTypeConfig() throws Exception { + try { + this.runtime.getConfig().addActorTypeConfig(null); + } catch (Exception ex) { + Assertions.assertTrue(ex instanceof IllegalArgumentException); + Assertions.assertTrue(ex.getMessage().contains("Add actor type config failed.")); + } + try { + this.runtime.getConfig().addRegisteredActorType(null); + } catch (Exception ex) { + Assertions.assertTrue(ex instanceof IllegalArgumentException); + Assertions.assertTrue(ex.getMessage().contains("Registered actor must have a type name.")); + } + } + @Test public void setDrainOngoingCallTimeout() throws Exception { this.runtime.getConfig().setDrainOngoingCallTimeout(Duration.ofSeconds(123));