Skip to content

Commit bf83b9b

Browse files
committed
Refactor and fixes. Added createMultiActorRefs
1 parent a5c3f45 commit bf83b9b

8 files changed

Lines changed: 225 additions & 66 deletions

File tree

README.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ The second thing we have to do is add the spawn dependency to the project.
9393
<dependency>
9494
<groupId>com.github.eigr</groupId>
9595
<artifactId>spawn-java-std-sdk</artifactId>
96-
<version>v0.7.1</version>
96+
<version>v0.8.0</version>
9797
</dependency>
9898
```
9999
We're also going to configure a few things for our application build to work, including compiling the protobuf files.
@@ -127,7 +127,7 @@ See below a full example of the pom.xml file:
127127
<dependency>
128128
<groupId>com.github.eigr</groupId>
129129
<artifactId>spawn-java-std-sdk</artifactId>
130-
<version>v0.7.1</version>
130+
<version>v0.8.0</version>
131131
</dependency>
132132
<dependency>
133133
<groupId>ch.qos.logback</groupId>
@@ -635,6 +635,7 @@ See an example:
635635
```Java
636636
package io.eigr.spawn.java.demo;
637637

638+
import io.eigr.spawn.api.ActorIdentity;
638639
import io.eigr.spawn.api.ActorRef;
639640
import io.eigr.spawn.api.actors.Value;
640641
import io.eigr.spawn.api.actors.ActorContext;
@@ -649,7 +650,7 @@ public class SideEffectActorExample {
649650
public Value setLanguage(Domain.Request msg, ActorContext<Domain.State> ctx) throws Exception {
650651
// Create a ActorReference to send side effect message
651652
ActorRef sideEffectReceiverActor = ctx.getSpawnSystem()
652-
.createActorRef("spawn-system", "mike", "abs_actor");
653+
.createActorRef(ActorIdentity.of("spawn-system", "mike", "abs_actor"));
653654

654655
return Value.at()
655656
.response(Domain.Reply.newBuilder()
@@ -683,6 +684,7 @@ package io.eigr.spawn.java.demo;
683684

684685
import io.eigr.spawn.api.actors.Value;
685686
import io.eigr.spawn.api.actors.ActorContext;
687+
import io.eigr.spawn.api.ActorIdentity;
686688
import io.eigr.spawn.api.ActorRef;
687689
import io.eigr.spawn.api.actors.annotations.Action;
688690
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
@@ -702,7 +704,7 @@ public class ForwardExample {
702704
log.info("State is present and value is {}", ctx.getState().get());
703705
}
704706
ActorRef forwardedActor = ctx.getSpawnSystem()
705-
.createActorRef("spawn-system", "mike", "abs_actor");
707+
.createActorRef(ActorIdentity.of("spawn-system", "mike", "abs_actor"));
706708

707709
return Value.at()
708710
.flow(Forward.to(forwardedActor, "setLanguage"))
@@ -725,6 +727,7 @@ package io.eigr.spawn.java.demo;
725727

726728
import io.eigr.spawn.api.actors.Value;
727729
import io.eigr.spawn.api.actors.ActorContext;
730+
import io.eigr.spawn.api.ActorIdentity;
728731
import io.eigr.spawn.api.ActorRef;
729732
import io.eigr.spawn.api.actors.annotations.Action;
730733
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
@@ -737,7 +740,7 @@ public class PipeActorExample {
737740
@Action
738741
public Value setLanguage(Domain.Request msg, ActorContext<Domain.State> ctx) throws Exception {
739742
ActorRef pipeReceiverActor = ctx.getSpawnSystem()
740-
.createActorRef("spawn-system", "joe");
743+
.createActorRef(ActorIdentity.of("spawn-system", "joe"));
741744

742745
return Value.at()
743746
.response(Domain.Reply.newBuilder()
@@ -832,7 +835,7 @@ In the sections below we will give some examples of how to invoke different type
832835
To invoke an actor named like the one we defined in section [Getting Started](#getting-started) we could do as follows:
833836

834837
```Java
835-
ActorRef joeActor = spawnSystem.createActorRef("spawn-system", "joe");
838+
ActorRef joeActor = spawnSystem.createActorRef(ActorIdentity.of("spawn-system", "joe"));
836839

837840
Domain.Request msg = Domain.Request.newBuilder()
838841
.setLanguage("erlang")
@@ -849,6 +852,7 @@ package io.eigr.spawn.java.demo;
849852

850853
import io.eigr.spawn.api.Spawn;
851854
import io.eigr.spawn.api.Spawn.SpawnSystem;
855+
import io.eigr.spawn.api.ActorIdentity;
852856
import io.eigr.spawn.api.ActorRef;
853857
import io.eigr.spawn.api.TransportOpts;
854858
import io.eigr.spawn.api.exceptions.SpawnException;
@@ -869,7 +873,7 @@ public class App {
869873

870874
spawnSystem.start();
871875

872-
ActorRef joeActor = spawnSystem.createActorRef("spawn-system", "joe");
876+
ActorRef joeActor = spawnSystem.createActorRef(ActorIdentity.of("spawn-system", "joe"));
873877

874878
Domain.Request msg = Domain.Request.newBuilder()
875879
.setLanguage("erlang")
@@ -916,7 +920,7 @@ public class AbstractActor {
916920
So you could define and call this actor at runtime like this:
917921

918922
```Java
919-
ActorRef mike = spawnSystem.createActorRef("spawn-system", "mike", "abs_actor");
923+
ActorRef mike = spawnSystem.createActorRef(ActorIdentity.of("spawn-system", "mike", "abs_actor"));
920924

921925
Domain.Request msg = Domain.Request.newBuilder()
922926
.setLanguage("erlang")
@@ -929,7 +933,7 @@ Domain.Reply reply = maybeResponse.get();
929933
The important part of the code above is the following snippet:
930934

931935
```Java
932-
ActorRef mike = spawnSystem.createActorRef("spawn-system", "mike", "abs_actor");
936+
ActorRef mike = spawnSystem.createActorRef(ActorIdentity.of("spawn-system", "mike", "abs_actor"));
933937
```
934938

935939
These tells Spawn that this actor will actually be named at runtime. The name parameter with value "mike"
@@ -956,6 +960,7 @@ It is possible to change the request waiting timeout using the invocation option
956960
```Java
957961
package io.eigr.spawn.java.demo;
958962

963+
import io.eigr.spawn.api.ActorIdentity;
959964
import io.eigr.spawn.api.ActorRef;
960965
import io.eigr.spawn.api.InvocationOpts;
961966
import io.eigr.spawn.api.Spawn;
@@ -973,7 +978,7 @@ public class App {
973978

974979
spawnSystem.start();
975980

976-
ActorRef joeActor = spawnSystem.createActorRef("spawn-system", "joe");
981+
ActorRef joeActor = spawnSystem.createActorRef(ActorIdentity.of("spawn-system", "joe"));
977982

978983
Domain.Request msg = Domain.Request.newBuilder()
979984
.setLanguage("erlang")
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package io.eigr.spawn.api;
2+
3+
import java.util.Objects;
4+
import java.util.Optional;
5+
import java.util.StringJoiner;
6+
7+
public final class ActorIdentity {
8+
private final String system;
9+
private final String name;
10+
private final Optional<String> maybeParent;
11+
12+
private ActorIdentity(String system, String name, String parent){
13+
this.system = system;
14+
this.name = name;
15+
this.maybeParent = Optional.ofNullable(parent);
16+
}
17+
18+
private ActorIdentity(String system, String name){
19+
this.system = system;
20+
this.name = name;
21+
this.maybeParent = Optional.empty();
22+
}
23+
24+
public static ActorIdentity of(String system, String name) {
25+
return new ActorIdentity(system, name);
26+
}
27+
28+
public static ActorIdentity of(String system, String name, String parent) {
29+
return new ActorIdentity(system, name, parent);
30+
}
31+
32+
public String getSystem() {
33+
return system;
34+
}
35+
36+
public String getName() {
37+
return name;
38+
}
39+
40+
public String getParent() {
41+
return maybeParent.get();
42+
}
43+
44+
public Optional<String> getMaybeParent() {
45+
return maybeParent;
46+
}
47+
48+
public boolean isParent() {
49+
return this.maybeParent.isPresent();
50+
}
51+
52+
@Override
53+
public boolean equals(Object o) {
54+
if (this == o) return true;
55+
if (o == null || getClass() != o.getClass()) return false;
56+
ActorIdentity actorIdentity = (ActorIdentity) o;
57+
return system.equals(actorIdentity.system) && name.equals(actorIdentity.name) && maybeParent.equals(actorIdentity.maybeParent);
58+
}
59+
60+
@Override
61+
public int hashCode() {
62+
return Objects.hash(system, name, maybeParent);
63+
}
64+
65+
@Override
66+
public String toString() {
67+
return new StringJoiner(", ", ActorIdentity.class.getSimpleName() + "[", "]")
68+
.add("system='" + system + "'")
69+
.add("name='" + name + "'")
70+
.add("maybeParent=" + maybeParent)
71+
.toString();
72+
}
73+
}

src/main/java/io/eigr/spawn/api/ActorRef.java

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.eigr.spawn.api;
22

33
import com.github.benmanes.caffeine.cache.Cache;
4-
import com.github.benmanes.caffeine.cache.Caffeine;
54
import com.google.protobuf.Any;
65
import com.google.protobuf.Empty;
76
import com.google.protobuf.GeneratedMessageV3;
@@ -10,27 +9,16 @@
109
import io.eigr.spawn.api.exceptions.ActorCreationException;
1110
import io.eigr.spawn.api.exceptions.ActorInvocationException;
1211
import io.eigr.spawn.api.exceptions.ActorNotFoundException;
13-
import io.eigr.spawn.api.exceptions.SpawnException;
1412
import io.eigr.spawn.internal.transport.client.SpawnClient;
1513

16-
import java.time.Duration;
17-
import java.util.HashMap;
18-
import java.util.Map;
19-
import java.util.Objects;
20-
import java.util.Optional;
14+
import java.util.*;
2115

2216
/**
2317
* ActorRef is responsible for representing an instance of an Actor
2418
*
2519
* @author Adriano Santos
2620
*/
2721
public final class ActorRef {
28-
private static final int CACHE_MAXIMUM_SIZE = 1_000;
29-
private static final int CACHE_EXPIRE_AFTER_WRITE_SECONDS = 60;
30-
private static final Cache<ActorOuterClass.ActorId, ActorRef> ACTOR_REF_CACHE = Caffeine.newBuilder()
31-
.maximumSize(CACHE_MAXIMUM_SIZE)
32-
.expireAfterWrite(Duration.ofSeconds(CACHE_EXPIRE_AFTER_WRITE_SECONDS))
33-
.build();
3422

3523
private final ActorOuterClass.ActorId actorId;
3624

@@ -46,20 +34,28 @@ private ActorRef(ActorOuterClass.ActorId actorId, SpawnClient client) {
4634
* </p>
4735
*
4836
* @param client is the client part of the Spawn protocol and is responsible for communicating with the Proxy.
49-
* @param system ActorSystem name of the actor that this ActorRef instance should represent
50-
* @param name the name of the actor that this ActorRef instance should represent
37+
* @param identity ActorIdentity name of the actor that this ActorRef instance should represent
5138
* @return the ActorRef instance
5239
* @since 0.0.1
5340
*/
54-
protected static ActorRef of(SpawnClient client, String system, String name) throws ActorCreationException {
55-
ActorOuterClass.ActorId actorId = buildActorId(system, name);
56-
ActorRef ref = ACTOR_REF_CACHE.getIfPresent(actorId);
41+
protected static ActorRef of(SpawnClient client, Cache<ActorOuterClass.ActorId, ActorRef> cache, ActorIdentity identity) throws ActorCreationException {
42+
ActorOuterClass.ActorId actorId;
43+
44+
if (identity.isParent()) {
45+
actorId = buildActorId(identity.getSystem(), identity.getName(), identity.getParent());
46+
47+
spawnActor(actorId, client);
48+
} else {
49+
actorId = buildActorId(identity.getSystem(), identity.getName());
50+
}
51+
52+
ActorRef ref = cache.getIfPresent(actorId);
5753
if (Objects.nonNull(ref)) {
5854
return ref;
5955
}
6056

6157
ref = new ActorRef(actorId, client);
62-
ACTOR_REF_CACHE.put(actorId, ref);
58+
cache.put(actorId, ref);
6359
return ref;
6460
}
6561

@@ -68,48 +64,57 @@ protected static ActorRef of(SpawnClient client, String system, String name) thr
6864
* </p>
6965
*
7066
* @param client is the client part of the Spawn protocol and is responsible for communicating with the Proxy.
71-
* @param system ActorSystem name of the actor that this ActorRef instance should represent
72-
* @param name the name of the actor that this ActorRef instance should represent
73-
* @param parent the name of the unnamed parent actor
67+
* @param identity ActorIdentity name of the actor that this ActorRef instance should represent
68+
* @param dispatchParent call proxy to spawn proxy or not
7469
* @return the ActorRef instance
7570
* @since 0.0.1
7671
*/
77-
protected static ActorRef of(SpawnClient client, String system, String name, String parent) throws ActorCreationException {
78-
ActorOuterClass.ActorId actorId = buildActorId(system, name, parent);
79-
ActorRef ref = ACTOR_REF_CACHE.getIfPresent(actorId);
72+
protected static ActorRef of(SpawnClient client, Cache<ActorOuterClass.ActorId, ActorRef> cache, ActorIdentity identity, boolean dispatchParent) throws ActorCreationException {
73+
ActorOuterClass.ActorId actorId = buildActorId(identity.getSystem(), identity.getName(), identity.getParent());
74+
ActorRef ref = cache.getIfPresent(actorId);
8075
if (Objects.nonNull(ref)) {
8176
return ref;
8277
}
8378

84-
spawnActor(actorId, client);
79+
if (dispatchParent) {
80+
spawnActor(actorId, client);
81+
}
82+
8583
ref = new ActorRef(actorId, client);
86-
ACTOR_REF_CACHE.put(actorId, ref);
84+
cache.put(actorId, ref);
8785
return ref;
8886
}
8987

90-
private static ActorOuterClass.ActorId buildActorId(String system, String name) {
88+
protected static ActorOuterClass.ActorId buildActorId(String system, String name) {
9189
ActorOuterClass.ActorId.Builder actorIdBuilder = ActorOuterClass.ActorId.newBuilder()
9290
.setSystem(system)
9391
.setName(name);
9492

9593
return actorIdBuilder.build();
9694
}
9795

98-
private static ActorOuterClass.ActorId buildActorId(String system, String name, String parent) {
96+
protected static ActorOuterClass.ActorId buildActorId(String system, String name, String parent) {
9997
return ActorOuterClass.ActorId.newBuilder()
10098
.setSystem(system)
10199
.setName(name)
102100
.setParent(parent)
103101
.build();
104102
}
105103

106-
private static void spawnActor(ActorOuterClass.ActorId actorId, SpawnClient client) throws ActorCreationException {
104+
protected static void spawnActor(ActorOuterClass.ActorId actorId, SpawnClient client) throws ActorCreationException {
107105
Protocol.SpawnRequest req = Protocol.SpawnRequest.newBuilder()
108106
.addActors(actorId)
109107
.build();
110108
client.spawn(req);
111109
}
112110

111+
protected static void spawnAllActors(List<ActorOuterClass.ActorId> actorIds, SpawnClient client) throws ActorCreationException {
112+
Protocol.SpawnRequest req = Protocol.SpawnRequest.newBuilder()
113+
.addAllActors(actorIds)
114+
.build();
115+
client.spawn(req);
116+
}
117+
113118
/**
114119
* <p>This method synchronously invokes an action on the actor that this ActorRef instance represents through the Spawn Proxy.
115120
* Used when it is not necessary to send parameters to the Action.

0 commit comments

Comments
 (0)