Skip to content

Commit

Permalink
Better api and javadoc
Browse files Browse the repository at this point in the history
  • Loading branch information
sleipnir committed Sep 8, 2023
1 parent d53671f commit dda771f
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 54 deletions.
43 changes: 20 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,29 +462,28 @@ public final class Joe {
}
```

Then you also need to register your Actor passing arguments like as follows:
Then you also need to register your Actor passing arguments like as follows:

```java
package io.eigr.spawn.java.demo;

import io.eigr.spawn.api.Spawn;
import io.eigr.spawn.api.actors.ActorRef;

import java.util.HashMap;
import java.util.Map;

public class App {
public static void main(String[] args) {
Map<String, String> actorConstructorArgs = new HashMap<>();
actorConstructorArgs.put("someKey", "someValue");

Spawn spawnSystem = new Spawn.SpawnSystem()
.create("spawn-system")
.withActor(Joe.class, actorConstructorArgs, arg -> new Joe((Map<String, String>) arg))
.build();
public static void main(String[] args) {
Map<String, String> actorConstructorArgs = new HashMap<>();
actorConstructorArgs.put("someKey", "someValue");

spawnSystem.start();
}
Spawn spawnSystem = new Spawn.SpawnSystem()
.create("spawn-system")
.withActor(Joe.class, actorConstructorArgs, arg -> new Joe((Map<String, String>) arg))
.build();

spawnSystem.start();
}
}
```

Expand Down Expand Up @@ -635,9 +634,9 @@ See an example:
```Java
package io.eigr.spawn.java.demo;

import io.eigr.spawn.api.ActorRef;
import io.eigr.spawn.api.actors.Value;
import io.eigr.spawn.api.actors.ActorContext;
import io.eigr.spawn.api.actors.ActorRef;
import io.eigr.spawn.api.actors.annotations.Action;
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
import io.eigr.spawn.api.actors.workflows.SideEffect;
Expand Down Expand Up @@ -683,7 +682,7 @@ package io.eigr.spawn.java.demo;

import io.eigr.spawn.api.actors.Value;
import io.eigr.spawn.api.actors.ActorContext;
import io.eigr.spawn.api.actors.ActorRef;
import io.eigr.spawn.api.ActorRef;
import io.eigr.spawn.api.actors.annotations.Action;
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
import io.eigr.spawn.api.actors.workflows.Forward;
Expand Down Expand Up @@ -725,7 +724,7 @@ package io.eigr.spawn.java.demo;

import io.eigr.spawn.api.actors.Value;
import io.eigr.spawn.api.actors.ActorContext;
import io.eigr.spawn.api.actors.ActorRef;
import io.eigr.spawn.api.ActorRef;
import io.eigr.spawn.api.actors.annotations.Action;
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
import io.eigr.spawn.api.actors.workflows.Pipe;
Expand Down Expand Up @@ -848,22 +847,20 @@ package io.eigr.spawn.java.demo;

import io.eigr.spawn.api.Spawn;
import io.eigr.spawn.api.Spawn.SpawnSystem;
import io.eigr.spawn.api.actors.ActorRef;
import io.eigr.spawn.api.ActorRef;
import io.eigr.spawn.api.TransportOpts;
import io.eigr.spawn.java.demo.domain.Domain;

import java.util.Optional;

public class App {
public static void main(String[] args) throws Exception {
Spawn spawnSystem = new SpawnSystem()
.create("spawn-system")
.withActor(Joe.class)
.withTransportOptions(
TransportOpts.builder()
.port(8091)
.proxyPort(9003)
.build()
TransportOpts.builder()
.port(8091)
.proxyPort(9003)
.build()
)
.build();

Expand Down Expand Up @@ -944,7 +941,7 @@ just a fire-and-forget call.
Therefore, to call an actor's function asynchronously, just use the invokeAsync method:

```Java
mike.invokeAsync("setLanguage", msg, Domain.Reply.class);
mike.invokeAsync("setLanguage", msg);
```

## Deploy
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.eigr.spawn.api.actors;
package io.eigr.spawn.api;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
Expand All @@ -7,7 +7,6 @@
import com.google.protobuf.GeneratedMessageV3;
import io.eigr.functions.protocol.Protocol;
import io.eigr.functions.protocol.actors.ActorOuterClass;
import io.eigr.spawn.api.InvocationOpts;
import io.eigr.spawn.api.exceptions.ActorInvokeException;
import io.eigr.spawn.api.exceptions.ActorNotFoundException;
import io.eigr.spawn.internal.transport.client.SpawnClient;
Expand All @@ -16,6 +15,12 @@
import java.util.Objects;
import java.util.Optional;

/**
* ActorRef is responsible for representing an instance of an Actor
*
* @author Adriano Santos
*
*/
public final class ActorRef {
private static final int CACHE_MAXIMUM_SIZE = 1_000;
private static final int CACHE_EXPIRE_AFTER_WRITE_SECONDS = 60;
Expand All @@ -32,8 +37,17 @@ private ActorRef(ActorOuterClass.ActorId actorId, SpawnClient client) {
this.client = client;
this.actorId = actorId;
}

public static ActorRef of(SpawnClient client, String system, String name) throws Exception {

/**
* <p>This method is responsible for creating instances of the ActorRef class
* </p>
* @param client is the client part of the Spawn protocol and is responsible for communicating with the Proxy.
* @param system ActorSystem name of the actor that this ActorRef instance should represent
* @param name the name of the actor that this ActorRef instance should represent
* @return the ActorRef instance
* @since 0.0.1
*/
protected static ActorRef of(SpawnClient client, String system, String name) throws Exception {
ActorOuterClass.ActorId actorId = buildActorId(system, name);
ActorRef ref = ACTOR_REF_CACHE.getIfPresent(actorId);
if (Objects.nonNull(ref)){
Expand All @@ -45,7 +59,17 @@ public static ActorRef of(SpawnClient client, String system, String name) throws
return ref;
}

public static ActorRef of(SpawnClient client, String system, String name, String parent) throws Exception {
/**
* <p>This method is responsible for creating instances of the ActorRef class when Actor is a UnNamed actor.
* </p>
* @param client is the client part of the Spawn protocol and is responsible for communicating with the Proxy.
* @param system ActorSystem name of the actor that this ActorRef instance should represent
* @param name the name of the actor that this ActorRef instance should represent
* @param parent the name of the unnamed parent actor
* @return the ActorRef instance
* @since 0.0.1
*/
protected static ActorRef of(SpawnClient client, String system, String name, String parent) throws Exception {
ActorOuterClass.ActorId actorId = buildActorId(system, name, parent);
ActorRef ref = ACTOR_REF_CACHE.getIfPresent(actorId);
if (Objects.nonNull(ref)){
Expand All @@ -58,70 +82,146 @@ public static ActorRef of(SpawnClient client, String system, String name, String
return ref;
}

public <T extends GeneratedMessageV3> Optional<Object> invoke(String cmd, Class<T> outputType) throws Exception {
Optional<Object> res = invokeActor(cmd, Empty.getDefaultInstance(), outputType, Optional.empty());
/**
* <p>This method synchronously invokes an action on the actor that this ActorRef instance represents through the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @param outputType the class that corresponds to the expected return type
* @return an Optional containing, or not, the response object to the Action call
* @since 0.0.1
*/
public <T extends GeneratedMessageV3> Optional<Object> invoke(String action, Class<T> outputType) throws Exception {
Optional<Object> res = invokeActor(action, Empty.getDefaultInstance(), outputType, Optional.empty());
if(res.isPresent() ){
return Optional.of(outputType.cast(res.get()));
}

return res;
}

public <T extends GeneratedMessageV3> Optional<Object> invoke(String cmd, Class<T> outputType, InvocationOpts opts) throws Exception {
Optional<Object> res = invokeActor(cmd, Empty.getDefaultInstance(), outputType, Optional.ofNullable(opts));
/**
* <p>This method synchronously invokes an action on the actor that this ActorRef instance represents through the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @param outputType the class that corresponds to the expected return type
* @param opts options that can be passed during the invocation of the Action.
* Please see the {@link io.eigr.spawn.api.InvocationOpts} class for more information
* @return an Optional containing, or not, the response object to the Action call
* @since 0.0.1
*/
public <T extends GeneratedMessageV3> Optional<Object> invoke(String action, Class<T> outputType, InvocationOpts opts) throws Exception {
Optional<Object> res = invokeActor(action, Empty.getDefaultInstance(), outputType, Optional.ofNullable(opts));
if(res.isPresent() ){
return Optional.of(outputType.cast(res.get()));
}

return res;
}

public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> Optional<Object> invoke(String cmd, S value, Class<T> outputType) throws Exception {
Optional<Object> res = invokeActor(cmd, value, outputType, Optional.empty());
/**
* <p>This method synchronously invokes an action on the actor that this ActorRef instance represents through the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @param value the action argument object.
* @param outputType the class that corresponds to the expected return type
* @return an Optional containing, or not, the response object to the Action call
* @since 0.0.1
*/
public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> Optional<Object> invoke(String action, S value, Class<T> outputType) throws Exception {
Optional<Object> res = invokeActor(action, value, outputType, Optional.empty());
if(res.isPresent() ){
return Optional.of(outputType.cast(res.get()));
}

return res;
}

public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> Optional<Object> invoke(String cmd, S value, Class<T> outputType, InvocationOpts opts) throws Exception {
Optional<Object> res = invokeActor(cmd, value, outputType, Optional.ofNullable(opts));
/**
* <p>This method synchronously invokes an action on the actor that this ActorRef instance represents through the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @param value the action argument object.
* @param outputType the class that corresponds to the expected return type
* @param opts options that can be passed during the invocation of the Action.
* Please see the {@link io.eigr.spawn.api.InvocationOpts} class for more information
* @return an Optional containing, or not, the response object to the Action call
* @since 0.0.1
*/
public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> Optional<Object> invoke(String action, S value, Class<T> outputType, InvocationOpts opts) throws Exception {
Optional<Object> res = invokeActor(action, value, outputType, Optional.ofNullable(opts));
if(res.isPresent() ){
return Optional.of(outputType.cast(res.get()));
}

return res;
}

public <T extends GeneratedMessageV3> void invokeAsync(String cmd, Class<T> outputType) throws Exception {
/**
* <p>This method asynchronously invokes an action on the actor that this ActorRef instance represents via the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @since 0.0.1
*/
public <T extends GeneratedMessageV3> void invokeAsync(String action) throws Exception {
InvocationOpts opts = InvocationOpts.builder().async(true).build();
invokeActor(cmd, Empty.getDefaultInstance(), outputType, Optional.of(opts));
invokeActor(action, Empty.getDefaultInstance(), null, Optional.of(opts));
}

public <T extends GeneratedMessageV3> void invokeAsync(String cmd, Class<T> outputType, InvocationOpts opts) throws Exception {
/**
* <p>This method asynchronously invokes an action on the actor that this ActorRef instance represents via the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @param opts options that can be passed during the invocation of the Action.
* Please see the {@link io.eigr.spawn.api.InvocationOpts} class for more information
* @since 0.0.1
*/
public <T extends GeneratedMessageV3> void invokeAsync(String action, InvocationOpts opts) throws Exception {
InvocationOpts mergedOpts = InvocationOpts.builder()
.async(true)
.delay(opts.getDelay())
.scheduledTo(opts.getScheduledTo())
.build();

invokeActor(cmd, Empty.getDefaultInstance(), outputType, Optional.ofNullable(mergedOpts));
invokeActor(action, Empty.getDefaultInstance(), null, Optional.ofNullable(mergedOpts));
}

public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> void invokeAsync(String cmd, S value, Class<T> outputType) throws Exception {
/**
* <p>This method asynchronously invokes an action on the actor that this ActorRef instance represents through the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @param value the action argument object.
* @since 0.0.1
*/
public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> void invokeAsync(String action, S value) throws Exception {
InvocationOpts opts = InvocationOpts.builder().async(true).build();
invokeActor(cmd, value, outputType, Optional.of(opts));
invokeActor(action, value, null, Optional.of(opts));
}

public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> void invokeAsync(String cmd, S value, Class<T> outputType, InvocationOpts opts) throws Exception {
/**
* <p>This method asynchronously invokes an action on the actor that this ActorRef instance represents through the Spawn Proxy.
* Used when it is not necessary to send parameters to the Action.
* </p>
* @param action name of the action to be called.
* @param value the action argument object.
* @param opts options that can be passed during the invocation of the Action.
* Please see the {@link io.eigr.spawn.api.InvocationOpts} class for more information
* @since 0.0.1
*/
public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> void invokeAsync(String action, S value, InvocationOpts opts) throws Exception {
InvocationOpts mergedOpts = InvocationOpts.builder()
.async(true)
.delay(opts.getDelay())
.scheduledTo(opts.getScheduledTo())
.build();

invokeActor(cmd, value, outputType, Optional.of(mergedOpts));
invokeActor(action, value, null, Optional.of(mergedOpts));
}

public String getActorSystem() {
Expand Down Expand Up @@ -187,7 +287,7 @@ private <T extends GeneratedMessageV3, S extends GeneratedMessageV3> Optional<Ob
case ACTOR_NOT_FOUND:
throw new ActorNotFoundException();
case OK:
if (resp.hasValue()) {
if (resp.hasValue() && Objects.nonNull(outputType)) {
return Optional.of(resp.getValue().unpack(outputType));
}
return Optional.empty();
Expand Down
Loading

0 comments on commit dda771f

Please sign in to comment.