Skip to content

Commit 4cea622

Browse files
committed
Update readme
1 parent debf74d commit 4cea622

File tree

2 files changed

+59
-27
lines changed

2 files changed

+59
-27
lines changed

README.md

+58-26
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ JVM User Language Support for [Spawn](https://github.com/eigr/spawn).
77
2. [Getting Started](#getting-started)
88
3. [Advanced Use Cases](#advanced-use-cases)
99
- [Types of Actors](#types-of-actors)
10+
- [Stateless Actors](#stateless-actors)
11+
- [Considerations about Spawn actors](#considerations-about-spawn-actors)
1012
- [Broadcast](#broadcast)
1113
- [Side Effects](#side-effects)
1214
- [Forward](#forward)
@@ -90,7 +92,7 @@ The second thing we have to do is add the spawn dependency to the project.
9092
<dependency>
9193
<groupId>com.github.eigr</groupId>
9294
<artifactId>spawn-java-std-sdk</artifactId>
93-
<version>v0.4.1</version>
95+
<version>v0.5.0</version>
9496
</dependency>
9597
```
9698
We're also going to configure a few things for our application build to work, including compiling the protobuf files.
@@ -124,7 +126,7 @@ See below a full example of the pom.xml file:
124126
<dependency>
125127
<groupId>com.github.eigr</groupId>
126128
<artifactId>spawn-java-std-sdk</artifactId>
127-
<version>v0.4.1</version>
129+
<version>v0.5.0</version>
128130
</dependency>
129131
<dependency>
130132
<groupId>ch.qos.logback</groupId>
@@ -286,12 +288,12 @@ package io.eigr.spawn.java.demo;
286288
import io.eigr.spawn.api.Value;
287289
import io.eigr.spawn.api.actors.ActorContext;
288290
import io.eigr.spawn.api.actors.annotations.Action;
289-
import io.eigr.spawn.api.actors.annotations.NamedActor;
291+
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
290292
import io.eigr.spawn.java.demo.domain.Domain;
291293
import org.slf4j.Logger;
292294
import org.slf4j.LoggerFactory;
293295

294-
@NamedActor(name = "joe", stateType = Domain.JoeState.class)
296+
@StatefulNamedActor(name = "joe", stateType = Domain.JoeState.class)
295297
public class Joe {
296298
private static final Logger log = LoggerFactory.getLogger(Joe.class);
297299

@@ -408,12 +410,12 @@ package io.eigr.spawn.java.demo;
408410
import io.eigr.spawn.api.Value;
409411
import io.eigr.spawn.api.actors.ActorContext;
410412
import io.eigr.spawn.api.actors.annotations.Action;
411-
import io.eigr.spawn.api.actors.annotations.NamedActor;
413+
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
412414
import io.eigr.spawn.java.demo.domain.Domain;
413415

414416
import java.util.Map;
415417

416-
@NamedActor(name = "joe", stateful = true, stateType = Domain.JoeState.class, channel = "test")
418+
@StatefulNamedActor(name = "joe", stateful = true, stateType = Domain.JoeState.class, channel = "test")
417419
public final class Joe {
418420
private final String someValue;
419421

@@ -509,6 +511,37 @@ during program execution. Otherwise, they behave like named actors.
509511
assigned to them at compile time. Pooled actors are generally used when higher performance is needed and are also
510512
recommended for handling serverless loads.
511513

514+
### Stateless Actors
515+
516+
In addition to these types, Spawn also allows the developer to choose Stateful actors, who need to maintain the state, or Stateless, those who do not need to maintain the state.
517+
For this the developer just needs to make use of the correct annotation. For example I could declare a Serverless Actor using the following code:
518+
519+
```java
520+
package io.eigr.spawn.test.actors;
521+
522+
import io.eigr.spawn.api.Value;
523+
import io.eigr.spawn.api.actors.ActorContext;
524+
import io.eigr.spawn.api.actors.annotations.Action;
525+
import io.eigr.spawn.api.actors.annotations.stateless.StatelessNamedActor;
526+
import io.eigr.spawn.java.test.domain.Actor;
527+
528+
@StatelessNamedActor(name = "test_joe", channel = "test.channel")
529+
public class JoeActor {
530+
@Action
531+
public Value hi(Actor.Request msg, ActorContext<?> context) {
532+
return Value.at()
533+
.response(Actor.Reply.newBuilder()
534+
.setResponse("Hello From Java")
535+
.build())
536+
.reply();
537+
}
538+
}
539+
```
540+
541+
Other than that the same Named, UnNamed types are supported. Just use the StatelessNamed or StatelessUnNamed annotations.
542+
543+
### Considerations about Spawn actors
544+
512545
Another important feature of Spawn Actors is that the lifecycle of each Actor is managed by the platform itself.
513546
This means that an Actor will exist when it is invoked and that it will be deactivated after an idle time in its execution.
514547
This pattern is known as [Virtual Actors](#virtual-actors) but Spawn's implementation differs from some other known
@@ -526,7 +559,7 @@ Actors in Spawn can subscribe to a thread and receive, as well as broadcast, eve
526559
To consume from a topic, you just need to configure the Actor annotation using the channel option as follows:
527560

528561
```Java
529-
@NamedActor(name = "joe", stateful = true, stateType = Domain.JoeState.class, channel = "test")
562+
@StatefulNamedActor(name = "joe", stateful = true, stateType = Domain.JoeState.class, channel = "test")
530563
```
531564
In the case above, the Actor `joe` was configured to receive events that are forwarded to the topic called `test`.
532565

@@ -540,7 +573,7 @@ package io.eigr.spawn.java.demo;
540573
import io.eigr.spawn.api.actors.workflows.Broadcast;
541574
// some imports omitted for brevity
542575

543-
@NamedActor(name = "joe", stateful = true, stateType = Domain.JoeState.class, channel = "test")
576+
@StatefulNamedActor(name = "joe", stateType = Domain.JoeState.class, channel = "test")
544577
public class Joe {
545578
@TimerAction(name = "hi", period = 60000)
546579
public Value hi(ActorContext<Domain.JoeState> context) {
@@ -582,11 +615,11 @@ import io.eigr.spawn.api.Value;
582615
import io.eigr.spawn.api.actors.ActorContext;
583616
import io.eigr.spawn.api.actors.ActorRef;
584617
import io.eigr.spawn.api.actors.annotations.Action;
585-
import io.eigr.spawn.api.actors.annotations.NamedActor;
618+
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
586619
import io.eigr.spawn.api.actors.workflows.SideEffect;
587620
import io.eigr.spawn.java.demo.domain.Domain;
588621

589-
@NamedActor(name = "side_effect_actor", stateful = true, stateType = Domain.State.class)
622+
@StatefulNamedActor(name = "side_effect_actor", stateful = true, stateType = Domain.State.class)
590623
public class SideEffectActorExample {
591624
@Action
592625
public Value setLanguage(Domain.Request msg, ActorContext<Domain.State> ctx) throws Exception {
@@ -628,13 +661,13 @@ import io.eigr.spawn.api.Value;
628661
import io.eigr.spawn.api.actors.ActorContext;
629662
import io.eigr.spawn.api.actors.ActorRef;
630663
import io.eigr.spawn.api.actors.annotations.Action;
631-
import io.eigr.spawn.api.actors.annotations.NamedActor;
664+
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
632665
import io.eigr.spawn.api.actors.workflows.Forward;
633666
import io.eigr.spawn.java.demo.domain.Domain;
634667
import org.slf4j.Logger;
635668
import org.slf4j.LoggerFactory;
636669

637-
@NamedActor(name = "routing_actor", stateful = true, stateType = Domain.State.class)
670+
@StatefulNamedActor(name = "routing_actor", stateful = true, stateType = Domain.State.class)
638671
public class ForwardExample {
639672
private static final Logger log = LoggerFactory.getLogger(ForwardExample.class);
640673

@@ -670,11 +703,11 @@ import io.eigr.spawn.api.Value;
670703
import io.eigr.spawn.api.actors.ActorContext;
671704
import io.eigr.spawn.api.actors.ActorRef;
672705
import io.eigr.spawn.api.actors.annotations.Action;
673-
import io.eigr.spawn.api.actors.annotations.NamedActor;
706+
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
674707
import io.eigr.spawn.api.actors.workflows.Pipe;
675708
import io.eigr.spawn.java.demo.domain.Domain;
676709

677-
@NamedActor(name = "pipe_actor", stateful = true, stateType = Domain.State.class)
710+
@StatefulNamedActor(name = "pipe_actor", stateful = true, stateType = Domain.State.class)
678711
public class PipeActorExample {
679712

680713
@Action
@@ -713,7 +746,7 @@ That is, data is saved at regular intervals asynchronously while the Actor is ac
713746
when the Actor suffers a deactivation, when it is turned off.
714747

715748
These snapshots happen from time to time. And this time is configurable through the ***snapshotTimeout*** property of
716-
the ***NamedActor*** or ***UnNamedActor*** annotation.
749+
the ***StatefulNamedActor*** or ***UnStatefulNamedActor*** annotation.
717750
However, you can tell the Spawn runtime that you want it to persist the data immediately synchronously after executing an Action.
718751
And this can be done in the following way:
719752

@@ -723,10 +756,10 @@ Example:
723756
import io.eigr.spawn.api.Value;
724757
import io.eigr.spawn.api.actors.ActorContext;
725758
import io.eigr.spawn.api.actors.annotations.Action;
726-
import io.eigr.spawn.api.actors.annotations.NamedActor;
759+
import io.eigr.spawn.api.actors.annotations.stateful.StatefulNamedActor;
727760
import io.eigr.spawn.java.demo.domain.Domain;
728761

729-
@NamedActor(name = "joe", stateful = true, stateType = Domain.JoeState.class)
762+
@StatefulNamedActor(name = "joe", stateType = Domain.JoeState.class)
730763
public final class Joe {
731764
@Action(inputType = Domain.Request.class)
732765
public Value setLanguage(Domain.Request msg, ActorContext<Domain.JoeState> context) {
@@ -743,8 +776,8 @@ public final class Joe {
743776

744777
The most important thing in this example is the use of the last parameter with the true value:
745778

746-
```Java
747-
.state(updateState("java"), true)
779+
```
780+
state(updateState("java"), true)
748781
```
749782

750783
It is this parameter that will indicate to the Spawn runtime that you want the data to be saved immediately after this
@@ -781,7 +814,7 @@ ActorRef joeActor = spawnSystem.createActorRef("spawn-system", "joe");
781814
.setLanguage("erlang")
782815
.build();
783816
Domain.Reply reply =
784-
(Domain.Reply) joeActor.invoke("setLanguage", msg, Domain.Reply.class, Optional.empty());
817+
(Domain.Reply) joeActor.invoke("setLanguage", msg, Domain.Reply.class);
785818
```
786819

787820
More detailed in complete main class:
@@ -813,7 +846,7 @@ public class App {
813846
.setLanguage("erlang")
814847
.build();
815848
Domain.Reply reply =
816-
(Domain.Reply) joeActor.invoke("setLanguage", msg, Domain.Reply.class, Optional.empty());
849+
(Domain.Reply) joeActor.invoke("setLanguage", msg, Domain.Reply.class);
817850
}
818851
}
819852
```
@@ -830,7 +863,7 @@ name at runtime:
830863
package io.eigr.spawn.java.demo;
831864
// omitted imports for brevity...
832865

833-
@UnNamedActor(name = "abs_actor", stateful = true, stateType = Domain.State.class)
866+
@UnStatefulNamedActor(name = "abs_actor", stateful = true, stateType = Domain.State.class)
834867
public class AbstractActor {
835868
@Action(inputType = Domain.Request.class)
836869
public Value setLanguage(Domain.Request msg, ActorContext<Domain.State> context) {
@@ -859,7 +892,7 @@ ActorRef mike = spawnSystem.createActorRef("spawn-system", "mike", "abs_actor");
859892
.setLanguage("erlang")
860893
.build();
861894
Domain.Reply reply =
862-
(Domain.Reply) mike.invoke("setLanguage", msg, Domain.Reply.class, Optional.empty());
895+
(Domain.Reply) mike.invoke("setLanguage", msg, Domain.Reply.class);
863896
```
864897

865898
The important part of the code above is the following snippet:
@@ -879,11 +912,10 @@ or asynchronously, where the callee doesn't care about the return value of the c
879912
In this context we should not confuse Spawn's asynchronous way with Java's concept of async like Promises because async for Spawn is
880913
just a fire-and-forget call.
881914

882-
Therefore, to call an actor's function asynchronously, just inform the parameter async using the InvocationOpts class with the value true:
915+
Therefore, to call an actor's function asynchronously, just use the invokeAsync method:
883916

884917
```Java
885-
InvocationOpts opts = InvocationOpts.builder().async(true).build();
886-
mike.invoke("setLanguage", msg, Domain.Reply.class, opts);
918+
mike.invokeAsync("setLanguage", msg, Domain.Reply.class);
887919
```
888920

889921
## Deploy

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<groupId>io.eigr.spawn</groupId>
55
<artifactId>spawn-java-std-sdk</artifactId>
66
<packaging>jar</packaging>
7-
<version>0.4.1</version>
7+
<version>0.5.0</version>
88
<name>spawn-java-std-sdk</name>
99
<url>http://maven.apache.org</url>
1010

0 commit comments

Comments
 (0)