LtDan33
LtDan33

Reputation: 311

Why is my Akka WebSocket Actor disconnecting/dying?

(Update/fix at bottom) I'm using the PlayFramework 2.x to create a simple WebSocket application using an actor. I'm able to get things working (sending echo ping) but I'm just wondering why the WebSocket disconnects after a short amount of time (roughly 30 seconds) if nothing is sent or received? I have a long-running (5-20 minute) process that I need to use the websocket to send back the notification when it ends.

I put a postStop to see if the actor is stopping and that is indeed hit. Maybe I just don't understand the actor lifecycle? I can't find anything in the docs on why an actor would be killed off in this case as there isn't a parent actor.

Controller:

public WebSocket socket() {
    return WebSocket.Text.accept(request ->
            ActorFlow.actorRef(
                    WebSocketActor::props,
                    actorSystem, materializer
            )
    );
}

Actor

public class WebSocketActor extends AbstractActor {
public static Props props(ActorRef out) {
    return Props.create(WebSocketActor.class, out);
}

private final ActorRef out;

public WebSocketActor(ActorRef out) {
    this.out = out;
    ActorSystem actorSystem = context().system();
}

@Override
public Receive createReceive() {

    return receiveBuilder()
            .match(String.class, message ->
                    out.tell("Message: " + message, self())
            )
   }

public void postStop() {
    System.out.println("I'm dying over here!");
}

}

UPDATE: Thanks @chunjef. I did, in fact, have to set the idle-timeout, but also had to start in production mode as some application.config values are not used in dev mode. Why they set it up like this I have no idea and is very frustrating. Per the official documentation:

Note: In dev mode, when you use the run command, your application.conf settings will not be picked up by the server. This is because in dev mode the server starts before the application classpath is available. There are several other options you’ll need to use instead.

Upvotes: 2

Views: 794

Answers (1)

Jeffrey Chung
Jeffrey Chung

Reputation: 19517

In your code, the actor's lifecycle is tied to the WebSocket connection: when the connection is closed, Play automatically stops the actor. And your connection is closing because it's inactive for too long.

From the Akka HTTP documentation (Akka HTTP is the underlying engine in Play):

Inactive WebSocket connections will be dropped according to the idle-timeout settings. In case you need to keep inactive connections alive, you can either tweak your idle-timeout or inject ‘keep-alive’ messages regularly.

You can change the idle-timeout settings as described in the above link or change the equivalent Play settings described here (the Play settings will override the Akka HTTP settings). For example, to completely disable the timeout via the Play configuration:

idleTimeout = infinite

Upvotes: 3

Related Questions