defclosed: Receive = { caseOpen => log.info("Opening resource") // step 3 - unstashAll when you switch the message handler unstashAll() context.become(open) case message => log.info(s"Stashing $message because I can't handle it in the closed state") // step 2 - stash away what you can't handle stash() }
defopen: Receive = { caseRead => // do some actual computation log.info(s"I have read $innerData") caseWrite(data) => log.info(s"I am writing $data") innerData = data caseClose => log.info("Closing resource") unstashAll() context.become(closed) case message => log.info(s"Stashing $message because I can't handle it in the open state") stash() } }
defhandleAuthentication(username: String, password: String) = { val originalSender = sender() // step 3 - ask the actor val future = authDb ? Read(username) // step 4 - handle the future for e.g. with onComplete future.onComplete { // step 5 most important // NEVER CALL METHODS ON THE ACTOR INSTANCE OR ACCESS MUTABLE STATE IN ONCOMPLETE. // avoid closing over the actor instance or mutable state caseSuccess(None) => originalSender ! AuthFailure(AUTH_FAILURE_NOT_FOUND) caseSuccess(Some(dbPassword)) => if (dbPassword == password) originalSender ! AuthSuccess else originalSender ! AuthFailure(AUTH_FAILURE_PASSWORD_INCORRECT) caseFailure(_) => originalSender ! AuthFailure(AUTH_FAILURE_SYSTEM) } } }