2013-10-09 13:11:53 +02:00
|
|
|
/**
|
2014-02-02 19:05:45 -06:00
|
|
|
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
2013-10-09 13:11:53 +02:00
|
|
|
*/
|
|
|
|
|
|
2013-09-14 14:19:18 +02:00
|
|
|
package docs.persistence;
|
|
|
|
|
|
2014-06-03 15:10:56 +02:00
|
|
|
import akka.actor.ActorPath;
|
2014-05-21 01:35:21 +02:00
|
|
|
import akka.actor.ActorRef;
|
|
|
|
|
import akka.actor.ActorSystem;
|
|
|
|
|
import akka.actor.Props;
|
|
|
|
|
import akka.actor.UntypedActor;
|
2014-06-03 15:10:56 +02:00
|
|
|
import akka.japi.Function;
|
2013-12-06 12:48:44 +01:00
|
|
|
import akka.japi.Procedure;
|
2013-09-14 14:19:18 +02:00
|
|
|
import akka.persistence.*;
|
2014-05-21 01:35:21 +02:00
|
|
|
import scala.Option;
|
|
|
|
|
import scala.concurrent.duration.Duration;
|
2014-06-03 15:10:56 +02:00
|
|
|
import java.io.Serializable;
|
2014-05-21 01:35:21 +02:00
|
|
|
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
2013-10-27 08:01:14 +01:00
|
|
|
import static java.util.Arrays.asList;
|
|
|
|
|
|
2013-09-14 14:19:18 +02:00
|
|
|
public class PersistenceDocTest {
|
|
|
|
|
|
2014-06-05 14:07:17 +02:00
|
|
|
public interface SomeOtherMessage {}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
public interface PersistentActorMethods {
|
2014-06-23 14:33:35 +02:00
|
|
|
//#persistence-id
|
|
|
|
|
public String persistenceId();
|
|
|
|
|
//#persistence-id
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recovery-status
|
|
|
|
|
public boolean recoveryRunning();
|
|
|
|
|
public boolean recoveryFinished();
|
|
|
|
|
//#recovery-status
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Object o1 = new Object() {
|
|
|
|
|
class MyActor extends UntypedActor {
|
2014-12-08 11:02:14 +01:00
|
|
|
ActorRef persistentActor;
|
2013-09-14 14:19:18 +02:00
|
|
|
|
|
|
|
|
public void onReceive(Object message) throws Exception {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void recover() {
|
|
|
|
|
//#recover-explicit
|
2014-12-08 11:02:14 +01:00
|
|
|
persistentActor.tell(Recover.create(), getSelf());
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-explicit
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Object o2 = new Object() {
|
2014-12-08 11:02:14 +01:00
|
|
|
abstract class MyPersistentActor1 extends UntypedPersistentActor {
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-start-disabled
|
|
|
|
|
@Override
|
2013-09-15 09:04:05 +02:00
|
|
|
public void preStart() {}
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-start-disabled
|
|
|
|
|
|
|
|
|
|
//#recover-on-restart-disabled
|
|
|
|
|
@Override
|
2013-09-15 09:04:05 +02:00
|
|
|
public void preRestart(Throwable reason, Option<Object> message) {}
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-restart-disabled
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
abstract class MyPersistentActor2 extends UntypedPersistentActor {
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-start-custom
|
|
|
|
|
@Override
|
2013-09-15 09:04:05 +02:00
|
|
|
public void preStart() {
|
2014-11-21 16:59:21 +01:00
|
|
|
getSelf().tell(Recover.create(457L), getSelf());
|
2013-09-14 14:19:18 +02:00
|
|
|
}
|
|
|
|
|
//#recover-on-start-custom
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor4 extends UntypedPersistentActor implements PersistentActorMethods {
|
2014-06-23 14:33:35 +02:00
|
|
|
//#persistence-id-override
|
2013-09-14 14:19:18 +02:00
|
|
|
@Override
|
2014-06-23 14:33:35 +02:00
|
|
|
public String persistenceId() {
|
|
|
|
|
return "my-stable-persistence-id";
|
2013-09-14 14:19:18 +02:00
|
|
|
}
|
2014-06-23 14:33:35 +02:00
|
|
|
//#persistence-id-override
|
2013-09-14 14:19:18 +02:00
|
|
|
@Override
|
2014-06-25 12:51:21 +02:00
|
|
|
public void onReceiveRecover(Object message) throws Exception {}
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveCommand(Object message) throws Exception {}
|
2013-09-14 14:19:18 +02:00
|
|
|
}
|
2014-03-24 15:35:54 +01:00
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor5 extends UntypedPersistentActor {
|
|
|
|
|
@Override
|
|
|
|
|
public String persistenceId() {
|
|
|
|
|
return "persistence-id";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#recovery-completed
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveRecover(Object message) {
|
|
|
|
|
if (message instanceof RecoveryCompleted) {
|
|
|
|
|
// perform init after recovery, before any other messages
|
2014-03-24 15:35:54 +01:00
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveCommand(Object message) throws Exception {
|
|
|
|
|
if (message instanceof String) {
|
|
|
|
|
// ...
|
|
|
|
|
} else {
|
|
|
|
|
unhandled(message);
|
2014-03-24 15:35:54 +01:00
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
}
|
|
|
|
|
//#recovery-completed
|
2014-03-24 15:35:54 +01:00
|
|
|
}
|
2013-09-14 14:19:18 +02:00
|
|
|
};
|
2014-11-21 16:59:21 +01:00
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
static Object fullyDisabledRecoveryExample = new Object() {
|
|
|
|
|
abstract class MyPersistentActor1 extends UntypedPersistentActor {
|
2014-11-21 16:59:21 +01:00
|
|
|
//#recover-fully-disabled
|
|
|
|
|
@Override
|
|
|
|
|
public void preStart() { getSelf().tell(Recover.create(0L), getSelf()); }
|
|
|
|
|
//#recover-fully-disabled
|
|
|
|
|
}
|
|
|
|
|
};
|
2014-06-03 15:10:56 +02:00
|
|
|
|
|
|
|
|
static Object atLeastOnceExample = new Object() {
|
|
|
|
|
//#at-least-once-example
|
|
|
|
|
|
|
|
|
|
class Msg implements Serializable {
|
|
|
|
|
public final long deliveryId;
|
|
|
|
|
public final String s;
|
|
|
|
|
|
|
|
|
|
public Msg(long deliveryId, String s) {
|
|
|
|
|
this.deliveryId = deliveryId;
|
|
|
|
|
this.s = s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Confirm implements Serializable {
|
|
|
|
|
public final long deliveryId;
|
|
|
|
|
|
|
|
|
|
public Confirm(long deliveryId) {
|
|
|
|
|
this.deliveryId = deliveryId;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MsgSent implements Serializable {
|
|
|
|
|
public final String s;
|
|
|
|
|
|
|
|
|
|
public MsgSent(String s) {
|
|
|
|
|
this.s = s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
class MsgConfirmed implements Serializable {
|
|
|
|
|
public final long deliveryId;
|
|
|
|
|
|
|
|
|
|
public MsgConfirmed(long deliveryId) {
|
|
|
|
|
this.deliveryId = deliveryId;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MyPersistentActor extends UntypedPersistentActorWithAtLeastOnceDelivery {
|
|
|
|
|
private final ActorPath destination;
|
2014-12-08 11:02:14 +01:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String persistenceId() { return "persistence-id"; }
|
2014-06-03 15:10:56 +02:00
|
|
|
|
|
|
|
|
public MyPersistentActor(ActorPath destination) {
|
|
|
|
|
this.destination = destination;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
@Override
|
2014-06-03 15:10:56 +02:00
|
|
|
public void onReceiveCommand(Object message) {
|
|
|
|
|
if (message instanceof String) {
|
|
|
|
|
String s = (String) message;
|
|
|
|
|
persist(new MsgSent(s), new Procedure<MsgSent>() {
|
|
|
|
|
public void apply(MsgSent evt) {
|
|
|
|
|
updateState(evt);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (message instanceof Confirm) {
|
|
|
|
|
Confirm confirm = (Confirm) message;
|
|
|
|
|
persist(new MsgConfirmed(confirm.deliveryId), new Procedure<MsgConfirmed>() {
|
|
|
|
|
public void apply(MsgConfirmed evt) {
|
|
|
|
|
updateState(evt);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
unhandled(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
@Override
|
2014-06-03 15:10:56 +02:00
|
|
|
public void onReceiveRecover(Object event) {
|
|
|
|
|
updateState(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateState(Object event) {
|
|
|
|
|
if (event instanceof MsgSent) {
|
|
|
|
|
final MsgSent evt = (MsgSent) event;
|
|
|
|
|
deliver(destination, new Function<Long, Object>() {
|
|
|
|
|
public Object apply(Long deliveryId) {
|
|
|
|
|
return new Msg(deliveryId, evt.s);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (event instanceof MsgConfirmed) {
|
|
|
|
|
final MsgConfirmed evt = (MsgConfirmed) event;
|
|
|
|
|
confirmDelivery(evt.deliveryId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MyDestination extends UntypedActor {
|
|
|
|
|
public void onReceive(Object message) throws Exception {
|
|
|
|
|
if (message instanceof Msg) {
|
|
|
|
|
Msg msg = (Msg) message;
|
|
|
|
|
// ...
|
|
|
|
|
getSender().tell(new Confirm(msg.deliveryId), getSelf());
|
|
|
|
|
} else {
|
|
|
|
|
unhandled(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#at-least-once-example
|
|
|
|
|
};
|
2013-09-14 14:19:18 +02:00
|
|
|
|
2013-09-26 09:14:43 +02:00
|
|
|
static Object o4 = new Object() {
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor extends UntypedPersistentActor {
|
|
|
|
|
@Override
|
|
|
|
|
public String persistenceId() { return "persistence-id"; }
|
|
|
|
|
|
|
|
|
|
//#save-snapshot
|
2013-09-26 09:14:43 +02:00
|
|
|
private Object state;
|
|
|
|
|
|
|
|
|
|
@Override
|
2014-12-08 11:02:14 +01:00
|
|
|
public void onReceiveCommand(Object message) {
|
2013-09-26 09:14:43 +02:00
|
|
|
if (message.equals("snap")) {
|
|
|
|
|
saveSnapshot(state);
|
2013-10-08 11:46:02 +02:00
|
|
|
} else if (message instanceof SaveSnapshotSuccess) {
|
|
|
|
|
SnapshotMetadata metadata = ((SaveSnapshotSuccess)message).metadata();
|
2013-09-26 09:14:43 +02:00
|
|
|
// ...
|
2013-10-08 11:46:02 +02:00
|
|
|
} else if (message instanceof SaveSnapshotFailure) {
|
|
|
|
|
SnapshotMetadata metadata = ((SaveSnapshotFailure)message).metadata();
|
2013-09-26 09:14:43 +02:00
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
//#save-snapshot
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveRecover(Object event) {
|
|
|
|
|
}
|
2013-09-26 09:14:43 +02:00
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
|
2013-09-26 09:14:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Object o5 = new Object() {
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor extends UntypedPersistentActor {
|
|
|
|
|
@Override
|
|
|
|
|
public String persistenceId() { return "persistence-id"; }
|
|
|
|
|
|
|
|
|
|
//#snapshot-offer
|
2013-09-26 09:14:43 +02:00
|
|
|
private Object state;
|
|
|
|
|
|
|
|
|
|
@Override
|
2014-12-08 11:02:14 +01:00
|
|
|
public void onReceiveRecover(Object message) {
|
2013-09-26 09:14:43 +02:00
|
|
|
if (message instanceof SnapshotOffer) {
|
|
|
|
|
state = ((SnapshotOffer)message).snapshot();
|
|
|
|
|
// ...
|
2014-12-08 11:02:14 +01:00
|
|
|
} else if (message instanceof RecoveryCompleted) {
|
|
|
|
|
// ...
|
|
|
|
|
} else {
|
2013-09-26 09:14:43 +02:00
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
//#snapshot-offer
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveCommand(Object message) {
|
|
|
|
|
}
|
2013-09-26 09:14:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MyActor extends UntypedActor {
|
2014-12-08 11:02:14 +01:00
|
|
|
ActorRef persistentActor;
|
2013-09-26 09:14:43 +02:00
|
|
|
|
|
|
|
|
public MyActor() {
|
2014-12-08 11:02:14 +01:00
|
|
|
persistentActor = getContext().actorOf(Props.create(MyPersistentActor.class));
|
2013-09-26 09:14:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onReceive(Object message) throws Exception {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void recover() {
|
|
|
|
|
//#snapshot-criteria
|
2014-12-08 11:02:14 +01:00
|
|
|
persistentActor.tell(Recover.create(SnapshotSelectionCriteria.create(457L,
|
|
|
|
|
System.currentTimeMillis())), null);
|
2013-09-26 09:14:43 +02:00
|
|
|
//#snapshot-criteria
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2013-10-27 08:01:14 +01:00
|
|
|
|
2014-01-17 06:58:25 +01:00
|
|
|
static Object o9 = new Object() {
|
2014-05-21 01:35:21 +02:00
|
|
|
//#persist-async
|
|
|
|
|
class MyPersistentActor extends UntypedPersistentActor {
|
2014-06-26 13:56:01 +02:00
|
|
|
@Override
|
|
|
|
|
public String persistenceId() { return "some-persistence-id"; }
|
2014-05-21 01:35:21 +02:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveRecover(Object msg) {
|
|
|
|
|
// handle recovery here
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveCommand(Object msg) {
|
|
|
|
|
sender().tell(msg, getSelf());
|
|
|
|
|
|
|
|
|
|
persistAsync(String.format("evt-%s-1", msg), new Procedure<String>(){
|
|
|
|
|
@Override
|
|
|
|
|
public void apply(String event) throws Exception {
|
|
|
|
|
sender().tell(event, self());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
persistAsync(String.format("evt-%s-2", msg), new Procedure<String>(){
|
|
|
|
|
@Override
|
|
|
|
|
public void apply(String event) throws Exception {
|
|
|
|
|
sender().tell(event, self());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#persist-async
|
|
|
|
|
|
|
|
|
|
public void usage() {
|
|
|
|
|
final ActorSystem system = ActorSystem.create("example");
|
2014-06-03 16:40:44 +02:00
|
|
|
//#persist-async-usage
|
2014-12-08 11:02:14 +01:00
|
|
|
final ActorRef persistentActor = system.actorOf(Props.create(MyPersistentActor.class));
|
|
|
|
|
persistentActor.tell("a", null);
|
|
|
|
|
persistentActor.tell("b", null);
|
2014-05-21 01:35:21 +02:00
|
|
|
|
|
|
|
|
// possible order of received messages:
|
|
|
|
|
// a
|
|
|
|
|
// b
|
|
|
|
|
// evt-a-1
|
|
|
|
|
// evt-a-2
|
|
|
|
|
// evt-b-1
|
|
|
|
|
// evt-b-2
|
2014-06-03 16:40:44 +02:00
|
|
|
//#persist-async-usage
|
2014-05-21 01:35:21 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Object o10 = new Object() {
|
2014-06-03 16:40:44 +02:00
|
|
|
//#defer
|
|
|
|
|
class MyPersistentActor extends UntypedPersistentActor {
|
2014-06-26 13:56:01 +02:00
|
|
|
@Override
|
|
|
|
|
public String persistenceId() { return "some-persistence-id"; }
|
2014-06-03 16:40:44 +02:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveRecover(Object msg) {
|
|
|
|
|
// handle recovery here
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveCommand(Object msg) {
|
|
|
|
|
final Procedure<String> replyToSender = new Procedure<String>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void apply(String event) throws Exception {
|
2014-11-21 16:59:21 +01:00
|
|
|
sender().tell(event, getSelf());
|
2014-06-03 16:40:44 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
persistAsync(String.format("evt-%s-1", msg), replyToSender);
|
|
|
|
|
persistAsync(String.format("evt-%s-2", msg), replyToSender);
|
|
|
|
|
defer(String.format("evt-%s-3", msg), replyToSender);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#defer
|
|
|
|
|
|
|
|
|
|
public void usage() {
|
|
|
|
|
final ActorSystem system = ActorSystem.create("example");
|
|
|
|
|
//#defer-caller
|
2014-12-08 11:02:14 +01:00
|
|
|
final ActorRef persistentActor = system.actorOf(Props.create(MyPersistentActor.class));
|
|
|
|
|
persistentActor.tell("a", null);
|
|
|
|
|
persistentActor.tell("b", null);
|
2014-06-03 16:40:44 +02:00
|
|
|
|
|
|
|
|
// order of received messages:
|
|
|
|
|
// a
|
|
|
|
|
// b
|
|
|
|
|
// evt-a-1
|
|
|
|
|
// evt-a-2
|
|
|
|
|
// evt-a-3
|
|
|
|
|
// evt-b-1
|
|
|
|
|
// evt-b-2
|
|
|
|
|
// evt-b-3
|
|
|
|
|
//#defer-caller
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Object o11 = new Object() {
|
2014-01-17 06:58:25 +01:00
|
|
|
//#view
|
2014-06-24 16:57:33 +02:00
|
|
|
class MyView extends UntypedPersistentView {
|
2014-06-26 13:56:01 +02:00
|
|
|
@Override
|
|
|
|
|
public String persistenceId() { return "some-persistence-id"; }
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String viewId() { return "my-stable-persistence-view-id"; }
|
2014-01-17 06:58:25 +01:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceive(Object message) throws Exception {
|
2014-06-24 16:57:33 +02:00
|
|
|
if (isPersistent()) {
|
|
|
|
|
// handle message from Journal...
|
|
|
|
|
} else if (message instanceof String) {
|
|
|
|
|
// handle message from user...
|
|
|
|
|
} else {
|
|
|
|
|
unhandled(message);
|
2014-01-17 06:58:25 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#view
|
|
|
|
|
|
|
|
|
|
public void usage() {
|
|
|
|
|
final ActorSystem system = ActorSystem.create("example");
|
|
|
|
|
//#view-update
|
|
|
|
|
final ActorRef view = system.actorOf(Props.create(MyView.class));
|
|
|
|
|
view.tell(Update.create(true), null);
|
|
|
|
|
//#view-update
|
|
|
|
|
}
|
|
|
|
|
};
|
2013-09-14 14:19:18 +02:00
|
|
|
}
|