Tomer Tomer - 2 months ago 5x
Scala Question

Update state in actor from within a future

Consider the following code sample:

class MyActor (httpClient: HttpClient) {

var canSendMore = true

override def receive: Receive = {
case PayloadA(name: String) => send(urlA)
case PayloadB(name: String) => send(urlB)

def send(url: String){
if (canSendMore) => canSendMore = response.canSendMore)
else {
Thread.sleep(5000) //this will be done in a more elegant way, it's just for the example. => canSendMore = response.canSendMore)

Each message handling will result in an async http request. (post return value is a Future[Response])
My problem is that I want to safely update counter ( At the moment there is a race condition)

BTW, I must somehow update counter in the same thread, or at least before any other message is processed by this actor.

Is this possible?


You can use become + stash combination to keep on stashing messages when the http request future is in process.

object FreeToProcess

case PayloadA(name: String)

class MyActor (httpClient: HttpClient) extends Actor with Stash {

  def canProcessReceive: Receive = {
    case PayloadA(name: String) => {
      // become an actor which just stashes messages
      context.become(canNotProcessReceive, discardOld = false){
        case Success(x) => {
          // Use your result
          self ! FreeToProcess
        case Failure(e) => {
          // Use your failure
          self ! FreeToProcess

  def canNotProcessReceive: Receive = {
    case CanProcess => {
      // replay stash to mailbox
      // start processing messages

    case msg => {