Skip to content

Commit d72f974

Browse files
committed
Add invoke operation
1 parent 56bbf57 commit d72f974

File tree

5 files changed

+113
-17
lines changed

5 files changed

+113
-17
lines changed

src/main/java/io/eigr/spawn/Spawn.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ public void start() throws Exception {
6767
registerActorSystem();
6868
}
6969

70-
public ActorRef createActorRef(String system, String name) {
70+
public ActorRef createActorRef(String system, String name) throws Exception {
7171
return ActorRef.of(this.client, system, name);
7272
}
7373

74-
public ActorRef createActorRef(String system, String name, String parent) {
74+
public ActorRef createActorRef(String system, String name, String parent) throws Exception {
7575
return ActorRef.of(this.client, system, name, parent);
7676
}
7777

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

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,68 @@
11
package io.eigr.spawn.api.actors;
22

3+
import com.google.protobuf.Any;
4+
import com.google.protobuf.Empty;
5+
import com.google.protobuf.GeneratedMessageV3;
6+
import io.eigr.functions.protocol.Protocol;
7+
import io.eigr.functions.protocol.actors.ActorOuterClass;
8+
import io.eigr.spawn.api.InvocationOpts;
9+
import io.eigr.spawn.api.exceptions.ActorInvokeException;
10+
import io.eigr.spawn.api.exceptions.ActorNotFoundException;
311
import io.eigr.spawn.internal.client.SpawnClient;
412

513
import java.util.Optional;
614

715
public final class ActorRef {
816

17+
private final ActorOuterClass.ActorId actorId;
18+
919
private final String name;
1020

1121
private final String system;
1222

1323
private final Optional<String> parent;
24+
1425
private final SpawnClient client;
1526

16-
private ActorRef(SpawnClient client, String system, String name) {
27+
private ActorRef(SpawnClient client, String system, String name) throws Exception {
1728
this.client = client;
1829
this.system = system;
1930
this.name = name;
2031
this.parent = Optional.empty();
32+
this.actorId = buildActorId();
33+
if (this.parent.isPresent()){
34+
makeActor();
35+
}
2136
}
22-
private ActorRef(SpawnClient client, String system, String name, String parent) {
37+
38+
private ActorRef(SpawnClient client, String system, String name, String parent) throws Exception {
2339
this.client = client;
2440
this.system = system;
2541
this.name = name;
2642
this.parent = Optional.of(parent);
43+
this.actorId = buildActorId();
44+
if (this.parent.isPresent()){
45+
makeActor();
46+
}
2747
}
2848

29-
public static ActorRef of(SpawnClient client, String system, String name) {
49+
50+
public static ActorRef of(SpawnClient client, String system, String name) throws Exception {
3051
return new ActorRef(client, system, name);
3152
}
3253

33-
public static ActorRef of(SpawnClient client, String system, String name, String parent) {
54+
public static ActorRef of(SpawnClient client, String system, String name, String parent) throws Exception {
3455
return new ActorRef(client, system, name, parent);
3556
}
3657

58+
public <T extends GeneratedMessageV3> Object invoke(String cmd, Class<T> outputType, Optional<InvocationOpts> opts) throws Exception {
59+
return invokeActor(cmd, Empty.getDefaultInstance(), outputType, opts);
60+
}
61+
62+
public <T extends GeneratedMessageV3, S extends GeneratedMessageV3> Object invoke(String cmd, S value, Class<T> outputType, Optional<InvocationOpts> opts) throws Exception {
63+
return invokeActor(cmd, value, outputType, opts);
64+
}
65+
3766
public String getActorSystem() {
3867
return this.system;
3968
}
@@ -53,4 +82,71 @@ public String getActorParentName() {
5382
public boolean isUnnamedActor() {
5483
return Optional.empty().isPresent();
5584
}
85+
86+
private ActorOuterClass.ActorId buildActorId() {
87+
ActorOuterClass.ActorId.Builder actorIdBuilder = ActorOuterClass.ActorId.newBuilder()
88+
.setSystem(this.system)
89+
.setName(this.name);
90+
91+
if (this.parent.isPresent()) {
92+
actorIdBuilder.setParent(this.parent.get());
93+
}
94+
95+
return actorIdBuilder.build();
96+
}
97+
98+
private void makeActor() throws Exception {
99+
Protocol.SpawnRequest req = Protocol.SpawnRequest.newBuilder()
100+
.addActors(this.actorId)
101+
.build();
102+
this.client.spawn(req);
103+
}
104+
105+
private <T extends GeneratedMessageV3, S extends GeneratedMessageV3> Object invokeActor(String cmd, S argument, Class<T> outputType, Optional<InvocationOpts> options) throws Exception {
106+
Protocol.InvocationRequest.Builder invocationRequestBuilder = Protocol.InvocationRequest.newBuilder();
107+
108+
if (options.isPresent()) {
109+
InvocationOpts opts = options.get();
110+
invocationRequestBuilder.setAsync(opts.isAsync());
111+
112+
if (opts.getDelay().isPresent() && !opts.getScheduledTo().isPresent()) {
113+
invocationRequestBuilder.setScheduledTo(opts.getDelay().get());
114+
} else if (opts.getScheduledTo().isPresent()) {
115+
invocationRequestBuilder.setScheduledTo(opts.getScheduleTimeInLong());
116+
}
117+
}
118+
119+
final ActorOuterClass.Actor actorRef = ActorOuterClass.Actor.newBuilder()
120+
.setId(this.actorId)
121+
.build();
122+
123+
Any commandArg = Any.pack(argument);
124+
125+
invocationRequestBuilder
126+
.setSystem(ActorOuterClass.ActorSystem.newBuilder().setName(this.system).build())
127+
.setActor(actorRef)
128+
.setActionName(cmd)
129+
.setValue(commandArg)
130+
.build();
131+
132+
Protocol.InvocationResponse resp = this.client.invoke(invocationRequestBuilder.build());
133+
final Protocol.RequestStatus status = resp.getStatus();
134+
switch (status.getStatus()) {
135+
case UNKNOWN:
136+
case ERROR:
137+
case UNRECOGNIZED:
138+
throw new ActorInvokeException(
139+
String.format("Unknown error when trying to invoke Actor %s", this.name));
140+
case ACTOR_NOT_FOUND:
141+
throw new ActorNotFoundException();
142+
case OK:
143+
if (resp.hasValue()) {
144+
return outputType.cast(resp.getValue()
145+
.unpack(outputType));
146+
}
147+
return null;
148+
}
149+
150+
throw new ActorNotFoundException();
151+
}
56152
}

src/main/java/io/eigr/spawn/internal/client/OkHttpSpawnClient.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
import io.eigr.functions.protocol.Protocol;
44
import okhttp3.*;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
57

68
import java.util.Objects;
79

810
public final class OkHttpSpawnClient implements SpawnClient {
11+
private static final Logger log = LoggerFactory.getLogger(OkHttpSpawnClient.class);
12+
913
public static final String SPAWN_MEDIA_TYPE = "application/octet-stream";
10-
//private static final Logger log = LoggerFactory.getLogger(OkHttpSpawnClient.class);
1114
private static final String SPAWN_REGISTER_URI = "/api/v1/system";
1215

1316
private static final String SPAWN_ACTOR_SPAWN = "/api/v1/system/%s/actors/spawn";
@@ -26,10 +29,8 @@ public OkHttpSpawnClient(String system, String proxyHost, int proxyPort) {
2629
this.client = new OkHttpClient();
2730
}
2831

29-
3032
@Override
3133
public Protocol.RegistrationResponse register(Protocol.RegistrationRequest registration) throws Exception {
32-
//log.debug("Send registration request");
3334
RequestBody body = RequestBody.create(registration.toByteArray(), MediaType.parse(SPAWN_MEDIA_TYPE));
3435

3536
Request request = new Request.Builder().url(makeURLFrom(SPAWN_REGISTER_URI)).post(body).build();
@@ -41,14 +42,13 @@ public Protocol.RegistrationResponse register(Protocol.RegistrationRequest regis
4142
Objects.requireNonNull(response.body()
4243
).bytes());
4344
} catch (Exception e) {
44-
//log.error("Error registering Actors", e);
45+
log.error("Error registering Actors", e);
4546
throw new Exception(e);
4647
}
4748
}
4849

4950
@Override
5051
public Protocol.SpawnResponse spawn(Protocol.SpawnRequest registration) throws Exception {
51-
//log.debug("Send registration request");
5252
RequestBody body = RequestBody.create(registration.toByteArray(), MediaType.parse(SPAWN_MEDIA_TYPE));
5353

5454
Request request = new Request.Builder()
@@ -62,7 +62,7 @@ public Protocol.SpawnResponse spawn(Protocol.SpawnRequest registration) throws E
6262
Objects.requireNonNull(response.body()
6363
).bytes());
6464
} catch (Exception e) {
65-
//log.error("Error registering Actors", e);
65+
log.error("Error registering Actors", e);
6666
throw new Exception(e);
6767
}
6868
}

src/main/java/io/eigr/spawn/internal/handlers/ActorServiceHandler.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ public ActorServiceHandler(final String system, final List<Entity> actors) {
5454

5555
@Override
5656
public void handle(HttpExchange exchange) throws IOException {
57-
log.debug("Received Actor Action Request. Exchange: {}", exchange);
58-
log.debug("Received Actor Action Request. RequestMethod: {}", exchange.getRequestMethod());
59-
57+
log.debug("Received Actor Action Request.");
6058

6159
if ("POST".equals(exchange.getRequestMethod())) {
6260
Protocol.ActorInvocationResponse response = handleRequest(exchange);

src/test/java/io/eigr/spawn/SpawnTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.eigr.spawn;
22

3+
import io.eigr.spawn.api.actors.ActorRef;
34
import junit.framework.Test;
45
import junit.framework.TestCase;
56
import junit.framework.TestSuite;
@@ -22,8 +23,9 @@ public static Test suite() {
2223
return new TestSuite(SpawnTest.class);
2324
}
2425

25-
public void testApp() {
26-
new Spawn.SpawnSystem().build();
26+
public void testApp() throws Exception {
27+
Spawn spawn = new Spawn.SpawnSystem().build();
28+
ActorRef actor = spawn.createActorRef("spawn-system", "joe");
2729
assertTrue(true);
2830
}
2931
}

0 commit comments

Comments
 (0)