2016-08-16 78 views
0

假設我有以下演員:序列演員問電話

class A extends Actor { 
    def receive = { 
     case Unlock => sender ! UnlockResponse (Boolean_code) 
     case Read => sender ! ReadResponse (somedata) 
     case Lock => sender ! LockResponse (Boolean_code) 
    } } 

我想write.a輔助方法,在那裏我可以打電話給開鎖,讀取和順序鎖,並從返回「somedata」在上一步(鎖定)完成後,方法調用方的ReadResponse已完成。

我喜歡理解方法,但是如何以更靈活的方式編寫它,例如,如果Unlock在第一步中返回UnlockResponse(true)時繼續讀取,但如果返回值爲UnlockResponse (假)?

+0

你只是想實現的東西像'semaphore'與演員? –

+0

您是否嘗試在for-comprehension中添加警戒條件以檢查解鎖請求的值? – cmbaxter

回答

1

正如我在我的評論說,只是用一個換理解,在其監護條件,就像這樣:

val result = 
    for{ 
    unlockResult <- (nActorRef ? Unlock).mapTo[UnlockResponse] 
    if unlockResult.result == true 
    readResult <- (anActorRef ? Read).mapTo[ReadResponse] 
    } yield readResult 

這種情況下,唯一的問題是,通過result代表的產生Future會當不符合警戒條件時失敗。如果這是你的問題,你想,也許已在Future包裝一個Option[ReadResult]代替,那麼你可以使用recover像這樣:

val result:Future[Option[ReadResult]] = 
    for{ 
    unlockResult <- (nActorRef ? Unlock).mapTo[UnlockResponse] 
    if unlockResult.result == true 
    readResult <- (anActorRef ? Read).mapTo[ReadResponse] 
    } yield Some(readResult) 

result.recover{case ex:NoSuchElementException => None} 
+0

謝謝。這種方法看起來更清潔,我可以使用警衛輕鬆控制過程。 –

1

對於您可以使用Scala Promises API的順序邏輯:

val promise = Promise[ReadResponse]() 
val unlockFuture = anActorRef ? Unlock 
unlockFuture.map{ 
    case UnlockResponse (true) => promise.completeWith(anActorRef ? Read) 
    case UnlockResponse (false) => p.failure(new IllegalStateException) 
} 

,然後根據結果,你可以這樣做

p.future.onComplete { 
    case Success(somedata) => { 
     processData(somedata) 
     anActorRef ! Lock 
    } 
    case Failure(t) => logger.error(t) 
} 

用相同的順序效果更好的解決方案可能是通過Actor實現成爲/不成熟,並且stash,其中事務邏輯由演員本身而不是發送者處理。

+0

謝謝。這看起來不錯,但是當我在Read()之前的序列中添加一個額外的演員調用時,我遇到了問題。我能按順序完成兩個期貨的結果,還是需要兩個承諾? –

+0

這是不正確的。無論解鎖的結果如何,您都可以在這裏讀取讀取內容,因爲該查詢操作不在應用於'unlockFuture'的'map'操作之外。如果你真的只想在解鎖成功的情況下解鎖讀取,則需要在解鎖結果爲真的情況下將該請求操作向下移動到'map'中。 – cmbaxter