Search code examples
scalaakkaactor

Scala Actor: ReceiveTimeout with Param


Is it possible to pass a parameter to ReceiveTimeout? I have the following code:

case ReceiveTimeout =>
      self ! BuildJobEvents(asperaClient.getWorkOrder(workOrderID), dateTime)

When I try to pass a parameter, but that is not valid. I looked at the documentation here, and did not see anything about using parameters either. Is it possible to pass a parameter to ReceiveTimeout? If not, how would I get around this?

Edit

I have an actor system that will log events to a table. Each event has a timestamp noting when it occurs. I need to pass this timestamp along the chain, so I can use it to determine if data (which has an updated_at timestamp) has actually changed.

Ex: When I call the API service, say I get an event like this:

Item {
  event1 {
    stated: 5:00pm,
    completed: 5:10pm
  },
  event1 {
    stated: 5:10pm
  }
  data: data
  updated_at: 5:11pm
}

I want to log event1 and event2 here. I also want to pass a dateTime value of 5:11 pm in the message, so we can use it for the next call:

Item {
  event1 {
    stated: 5:00pm,
    completed: 5:10pm
  },
  event1 {
    stated: 5:10pm,
    completed: 5:12pm
  }
  data: data
  updated_at: 5:12pm
}

In this case, I do not want to log event1, because the timestamp is before 5:11 and therefore, the actor has already logged it. I would log event2 again though.


Solution

  • You might be looking for context.become which you can use to implement a light weight state machine.

    class MyActor extends Actor {
    
      override def receive: Receive = {
        case something =>
          context.setReceiveTimeout(5.seconds)
          context.become(waitForTimeout(something))
      }
    
      private[this] def waitForTimeout(param: Any): Receive = {
        case ReceiveTimeout =>
          // do something with something
      }
    }
    

    You have more possibilities if you mixin the FSM trait.

    EDIT

    Reading your event examples, maybe something like this?

    private def receiveNextEvent(lastTimestamp: DateTime): Receive = {
      case event =>
       if (event.stated > lastTimestamp) {
         logEvent(event)
         context.become(receiveNextEvent(event.stated)
       }
    }