2017-02-20 25 views
0

私は複数の状態の俳優を実装しており、メッセージを失うことはないようにStashを使用しています。私の状態は初期化中(DBから取得)、実行中(要求処理中)、更新中(状態の更新中)です。 私の問題は、将来解決するためにunstashAll()にしようとするとメッセージが失われることです。akka unstashAll not working

def initializing: Receive = { 
case Initialize => 
    log.info("initializing") 
    (for { 
    items1 <- db.getItems("1") 
    items2 <- db.getItems("2") 
    } yield items1 ::: items2) map {items => 
    unstashAll() 
    context.become(running(items)) 
    } 
case r => 
    log.debug(s"actor received message: $r while initializing and stashed it for further processing") 
    stash()} 

私はこの

def initializing: Receive = { 
case Initialize => 
    log.info("initializing") 
    (for { 
    items1 <- db.getItems("1") 
    items2 <- db.getItems("2") 
    } yield items1 ::: items2) pipeTo self 
    context.become({ 
    case items: List[Item] => 
     unstashAll() 
     context.become(running(items)) 
    case r => 
     log.debug(s"actor received message: $r while initializing and stashed it for further processing") 
     stash() 
    }) 
case r => 
    log.debug(s"actor received message: $r while initializing and stashed it for further processing") 
    stash()} 

に私の実装を変更することで、それを固定された第一が機能しなかった理由を誰もが説明できますか?

答えて

1

私はunstashAll部分がうまく動作すると思います。問題は、将来のコールバックの一環として、あなたがcontext.becomeと一緒にそれを実行していたことです。

これは、mapブロック内のコードが、アクタのシーケンシャル処理の予測可能性をエスケープすることを意味します。言い換えれば、これは起こることができる:

  1. あなたは俳優があなたのメッセージを一つずつ拾っunstashAll
  2. あなたのメッセージは、俳優のメールボックス
  3. に戻され呼び出します。まだコンテキストが変更されていないので、彼らは再び隠され
  4. あなたのコンテキストは最終的にrunningになります(が、それは遅すぎます)

ソリューションです - あなたが見つけたとして - 基本的に送信しpipeToパターンを、 Future結果はアクターにメッセージとして送られます。これにより、すべてが順次かつ予測可能になります。