Pergunta

Eu tenho um aplicativo Play Framework 2 que também usa Akka.eu tenho um Actor que recebe mensagens de um sistema remoto, a quantidade dessas mensagens pode ser muito grande.Depois que uma mensagem é recebida, eu a registro no banco de dados (usando o Ebean ORM integrado) e continuo a processá-la.Eu não me importo com a rapidez com que esse registro de banco de dados funciona, mas definitivamente não deve bloquear o processamento posterior.Aqui está um exemplo de código simplificado:

public class MessageReceiver extends UntypedActor {

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof ServerMessage) {
            ServerMessage serverMessage = (ServerMessage) message;
            ServerMessageModel serverMessageModel = new ServerMessageModel(serverMessage);
            serverMessageModel.save();
            //now send the message to another actor for further processing
        } else {
            unhandled(message);
        }
    }
}

Pelo que entendi, a inserção do banco de dados está bloqueando essa realização, portanto não atende às minhas necessidades.Mas não consigo descobrir como desbloqueá-lo.Eu li sobre o Future class, mas não consigo fazê-lo funcionar, pois deve retornar algum valor, e serverMessageModel.save(); retorna voidEntendo que escrever muitas mensagens, uma por uma, no banco de dados é ineficiente, mas esse não é o problema no momento.

Estou certo de que esta implementação está bloqueando?Se for, como posso fazê-lo funcionar de forma assíncrona?

Foi útil?

Solução

Se você deseja usar Future - construa um Akka Future com um Callable (classe anônima), cujo apply() irá realmente implementar o código de salvamento do banco de dados.Na verdade, você pode colocar tudo isso (criação futura e aplicação ()) em sua classe ServerMessageModel - talvez chame-a de asynchSave ().Seu Futuro talvez Futuro onde o status é o resultado de asynchSave...

public Future<Status> asyncSave(...) { /* should the params be ServerMessageModel? */
  return future(new Callable<Status>() {
     public Status call() {
        /* do db work here */
     }
 }

No seu onReceive você pode contar ao outro ator.OBSERVAÇÃO:se você quiser ter certeza de que está disparando o comando para o outro ator após o retorno desse futuro, você pode usar o onSuccess do Future.

Future<Status> f = serverMessageModel.asyncSave();
f.onSuccess(otherActor.tell(serverMessage, self());

Você também pode lidar com falhas ...ver http://doc.akka.io/docs/akka/2.3.4/java/futures.html para mais detalhes.

Espero que ajude.

Outras dicas

A solução futura parece boa para mim.Não usei Futures de Java, mas você pode retornar um número inteiro ou string arbitrário se definitivamente precisar de algum valor de retorno.

Outra opção é enviar essa mensagem para algum outro ator que faria o salvamento no banco de dados.Então você deve certificar-se de que a caixa de correio desse ator não fique lotada.

Você considerou akka-persistência por esta?Talvez isso seja adequado ao seu caso de uso.

Persista o estado do ator com a extensão akka-persistence de Martin Krasser e meu provedor de persistência jdbc akka persistence jdbc https://github.com/dnvriend/akka-persistence-jdbc

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top