akka.actor.Stash Scala Examples

The following examples show how to use akka.actor.Stash. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: RareBooks.scala    From reactive-application-development-scala   with Apache License 2.0 5 votes vote down vote up
package com.rarebooks.library

import akka.actor.{ Actor, ActorLogging, OneForOneStrategy, Props, Stash, SupervisorStrategy }
import akka.routing.{ ActorRefRoutee, Router, RoundRobinRoutingLogic }
import scala.concurrent.duration.{ MILLISECONDS => Millis, FiniteDuration, Duration }

object RareBooks {

  case object Close
  case object Open
  case object Report

  def props: Props =
    Props(new RareBooks)
}

class RareBooks extends Actor with ActorLogging with Stash {

  import context.dispatcher
  import RareBooks._
  import RareBooksProtocol._

  override val supervisorStrategy: SupervisorStrategy = {
    val decider: SupervisorStrategy.Decider = {
      case Librarian.ComplainException(complain, customer) =>
        customer ! Credit()
        log.info(s"RareBooks sent customer $customer a credit")
        SupervisorStrategy.Restart
    }
    OneForOneStrategy()(decider orElse super.supervisorStrategy.decider)
  }

  private val openDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.open-duration", Millis), Millis)

  private val closeDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.close-duration", Millis), Millis)

  private val nbrOfLibrarians: Int = context.system.settings.config getInt "rare-books.nbr-of-librarians"

  private val findBookDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.librarian.find-book-duration", Millis), Millis)

  private val maxComplainCount: Int = context.system.settings.config getInt "rare-books.librarian.max-complain-count"

  var requestsToday: Int = 0
  var totalRequests: Int = 0

  var router: Router = createLibrarian()

  context.system.scheduler.scheduleOnce(openDuration, self, Close)

  
  protected def createLibrarian(): Router = {
    var cnt: Int = 0
    val routees: Vector[ActorRefRoutee] = Vector.fill(nbrOfLibrarians) {
      val r = context.actorOf(Librarian.props(findBookDuration, maxComplainCount), s"librarian-$cnt")
      cnt += 1
      ActorRefRoutee(r)
    }
    Router(RoundRobinRoutingLogic(), routees)
  }
} 
Example 2
Source File: AkkaMember.scala    From akka-kubernetes-tests   with Apache License 2.0 5 votes vote down vote up
package akka.kubernetes.sample

import akka.actor.{Actor, Stash}
import akka.cluster.sharding.ShardRegion
import akka.cluster.singleton.{ClusterSingletonProxy, ClusterSingletonProxySettings}
import akka.event.Logging
import akka.kubernetes.sample.AkkaBoss.{GoToJobCentre, JobSpec, WhatCanIDo}
import akka.kubernetes.sample.AkkaMember.Hello

case object AkkaMember {
  case class Hello(name: String)

  val extractEntityId: ShardRegion.ExtractEntityId = {
    case msg @ Hello(id) ⇒ (id, msg)
  }

  val numberOfShards = 100

  val extractShardId: ShardRegion.ExtractShardId = {
    case Hello(id) ⇒ math.abs(id.hashCode % numberOfShards).toString
  }
}

class AkkaMember() extends Actor with Stash {
  val bossProxy = context.system.actorOf(
    ClusterSingletonProxy.props(singletonManagerPath = "/user/boss",
                                settings = ClusterSingletonProxySettings(context.system))
  )

  val name = self.path.name
  val log = Logging(this)

  override def preStart(): Unit = {
    // TODO retry
    log.info("/me good morning {}", name)
    bossProxy ! WhatCanIDo(name)
  }

  override def receive: Receive = {
    case JobSpec(roles) =>
      log.info("I'm part of the team. I can do {}", roles)
      unstashAll()
      context.become(ready(roles))
    case GoToJobCentre(n) =>
      log.info("Seems I am not in the team :( I'll go fruit picking")
      context.stop(self)
    case _ =>
      stash()
  }

  def ready(roles: Set[String]): Receive = {
    case Hello(_) =>
      sender() ! s"hello from $name. What can I do for you? It better be in ${roles.mkString(", ")}"
    case _ =>
      sender() ! "what?"
  }
} 
Example 3
Source File: NoConcurrentRepoChange.scala    From metronome   with Apache License 2.0 5 votes vote down vote up
package dcos.metronome
package repository

import akka.actor.{Actor, ActorLogging, ActorRef, Stash}

import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NonFatal
import scala.util.{Failure, Success}

trait NoConcurrentRepoChange[Id, Model, Data] extends Actor with ActorLogging with Stash {
  import NoConcurrentRepoChange._

  final def repoChange(
      change: => Future[Model],
      data: Data,
      onSuccess: (ActorRef, Model, Data) => Change,
      onFailed: (ActorRef, Throwable, Data) => Failed
  )(implicit ec: ExecutionContext): Unit = {
    val from = sender()
    try {
      val changed = change //can throw an exception, so execute before we enter waiting state
      context.become(waitForPersisted, discardOld = false)
      changed.onComplete {
        case Success(result) => self ! onSuccess(from, result, data)
        case Failure(ex) => self ! onFailed(from, ex, data)
      }
    } catch {
      case NonFatal(ex) =>
        log.error(ex, "Could not apply repository change")
        notifySender(from, onFailed(from, ex, data))
    }
  }

  private[this] def waitForPersisted: Receive = {
    case event: Failed =>
      log.error(event.ex, "Repository change failed")
      notifySender(event.sender, event)
    case event: Change =>
      notifySender(event.sender, event)
    case _ => stash()
  }

  private[this] def notifySender(recipient: ActorRef, message: Any): Unit = {
    context.unbecome()
    recipient ! message
    unstashAll()
  }
}

object NoConcurrentRepoChange {

  trait Change {
    def sender: ActorRef
  }

  trait Failed {
    def sender: ActorRef
    def ex: Throwable
  }
} 
Example 4
Source File: LoadContentOnStartup.scala    From metronome   with Apache License 2.0 5 votes vote down vote up
package dcos.metronome
package repository

import akka.actor.{Actor, ActorLogging, Stash}
import mesosphere.marathon.StoreCommandFailedException
import org.apache.zookeeper.KeeperException.NoNodeException

import scala.concurrent.Future
import scala.util.control.NonFatal
import scala.util.{Failure, Success}

trait LoadContentOnStartup[Id, Model] extends Actor with Stash with ActorLogging {
  import LoadContentOnStartup._

  //TODO: change me to zk ec
  import context.dispatcher

  override def preStart(): Unit = {
    super.preStart()
    context.become(waitForInit)
    loadAll()
  }

  def repo: Repository[Id, Model]
  def initialize(specs: List[Model]): Unit

  def waitForInit: Receive = {
    case init: Init[Model] =>
      initialize(init.result)
      context.become(receive)
      unstashAll()
    case _ => stash()
  }

  def loadAll(): Unit = {
    val loadAllFuture = repo.ids().flatMap { ids =>
      Future.sequence(ids.map(id => getModel(id))).map(_.flatten.toList)
    }
    val me = self
    loadAllFuture.onComplete {
      case Success(result) => me ! Init(result)
      case Failure(ex) =>
        log.error(ex, "Can not load initial data. Give up.")
        System.exit(-1)
    }
  }

  private def getModel(id: Id): Future[Option[Model]] = {
    repo.get(id).recoverWith {
      case ex: StoreCommandFailedException =>
        ex.getCause match {
          case cause: NoNodeException =>
            log.error(
              s"ID $id or job-specs znode missing. Zk will need to be manually repaired.  Exception message: ${cause.getMessage}"
            )
            Future.successful(None)
          case NonFatal(cause) =>
            log
              .error(s"Unexpected exception occurred in reading zk at startup.  Exception message: ${cause.getMessage}")
            // We need crash strategy similar to marathon, for now we can NOT continue with such a zk failure.
            System.exit(-1)
            Future.failed(cause)
        }
    }
  }
}

object LoadContentOnStartup {
  case class Init[T](result: List[T])
} 
Example 5
Source File: StashCubeSvc.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.unicomplex.stashcube

import akka.actor.{Actor, Stash}
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer
import akka.util.ByteString

import scala.collection.mutable.ListBuffer

class StashCubeSvc extends Actor with Stash {

	private val msgList = new ListBuffer[String]()

  implicit val am = ActorMaterializer()
  import context.dispatcher

	override def receive: Receive = {
		case req@HttpRequest(HttpMethods.POST, _, _, _, _) =>
			stash()
			val resp = HttpResponse(status = StatusCodes.Accepted, entity = HttpEntity("Stashed away!"))
      sender() ! resp
		case req@HttpRequest(HttpMethods.PUT, _, _, _, _) =>
			context.become(report)
      val resp = HttpResponse(status = StatusCodes.Created, entity = HttpEntity("Un-stashed"))
      sender() ! resp
      unstashAll()
		case req@HttpRequest(HttpMethods.GET, _, _, _, _) =>
			val resp = HttpResponse(entity = msgList.toSeq.toString())
			sender() ! resp
	}

	def report: Receive = {
		case req@HttpRequest(HttpMethods.POST, _, _, _, _) =>
			req.entity.dataBytes.runFold(ByteString(""))(_ ++ _) map(_.utf8String) foreach(msgList.append(_))
		case req@HttpRequest(HttpMethods.GET, _, _, _, _) =>
			val resp = HttpResponse(entity = msgList.toSeq.toString())
			sender() ! resp
	}
} 
Example 6
Source File: SequentialFutureProcessing.scala    From NSDb   with Apache License 2.0 5 votes vote down vote up
package io.radicalbit.nsdb.cluster.actor

import akka.actor.{Actor, ActorRef, Stash, Status}
import io.radicalbit.nsdb.cluster.actor.SequentialFutureProcessing.{Continue, PipeableFutureWithContinue}
import io.radicalbit.nsdb.common.protocol.NSDbSerializable

import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}


    def pipeToWithEffect(recipient: ActorRef)(effect: T => Unit)(
        implicit sender: ActorRef = Actor.noSender): Future[T] = {
      future andThen {
        case Success(r) =>
          effect(r)
          recipient ! r
          sender ! Continue
        case Failure(f) =>
          recipient ! Status.Failure(f)
          sender ! Continue
      }
      future
    }

  }
} 
Example 7
Source File: BinaryNode.scala    From ingraph   with Eclipse Public License 1.0 5 votes vote down vote up
package ingraph.ire.nodes.binary

import akka.actor.{Actor, Stash}
import ingraph.ire.messages._
import ingraph.ire.messages.{Forwarder, TerminatorHandler}

abstract class BinaryNode(val expectedTerminatorCount: Int = 2) extends Actor with Forwarder with Stash with TerminatorHandler {
  val name = self.path.name
  var primaryPause: Option[Pause] = None
  var secondaryPause: Option[Pause] = None

  def onPrimary(changeSet: ChangeSet)

  def onSecondary(changeSet: ChangeSet)

  override def receive: Actor.Receive = {
    case Primary(reteMessage: ReteMessage) => {
      primaryPause match {
        case Some(pause) => {
          reteMessage match {
            case resume: Resume => {
              if (resume.messageID == pause.messageID)
                primaryPause = None
              if (secondaryPause.isEmpty)
                unstashAll()
            }
            case terminator: TerminatorMessage => {
              if (terminator.messageID == pause.messageID)
                handleTerminator(terminator)
              else
                stash()
            }
            case other => stash()
          }
        }
        case None => reteMessage match {
          case pause: Pause => primaryPause = Some(pause)
          case cs: ChangeSet => onPrimary(cs); // printForwarding(cs)
          case t: TerminatorMessage => handleTerminator(t)
        }
      }
    }
    case Secondary(reteMessage: ReteMessage) => {
      secondaryPause match {
        case Some(pause) => {
          reteMessage match {
            case resume: Resume => {
              if (resume.messageID == pause.messageID)
                secondaryPause = None
              if (primaryPause.isEmpty)
                unstashAll()
            }
            case terminator: TerminatorMessage => {
              if (terminator.messageID == pause.messageID)
                handleTerminator(terminator)
              else
                stash()
            }
            case other => stash()
          }
        }
        case None => reteMessage match {
          case pause: Pause => secondaryPause = Some(pause)
          case cs: ChangeSet => onSecondary(cs); //printForwarding(cs)
          case t: TerminatorMessage => handleTerminator(t)
        }

      }
    }
    case _: SizeRequest => sender() ! onSizeRequest()
    case other: ReteMessage =>
      throw new UnsupportedOperationException(
        s"$name received raw message, needs to be wrapped as Primary or Secondary")
  }

  def onSizeRequest(): Long
} 
Example 8
Source File: UnaryNode.scala    From ingraph   with Eclipse Public License 1.0 5 votes vote down vote up
package ingraph.ire.nodes.unary

import akka.actor.{Actor, Stash}
import ingraph.ire.messages._
import ingraph.ire.messages.{Forwarder, TerminatorHandler}

abstract class UnaryNode(val expectedTerminatorCount: Int = 1) extends Actor with Forwarder with Stash with TerminatorHandler {
  val name = self.path.name

  def onChangeSet(changeSet: ChangeSet)

  override def receive: Actor.Receive = {
    case pause: Pause => context.become({
      case resume: Resume => {
        if (resume.messageID == pause.messageID) {
          context.unbecome()
          unstashAll()
        } else stash()
      }
      case terminator: TerminatorMessage => handleTerminator(terminator)
      case _ => stash()
    })
    case changeSet: ChangeSet => onChangeSet(changeSet)
    case terminator: TerminatorMessage => handleTerminator(terminator)
    case Primary | Secondary =>
      throw new UnsupportedOperationException(s"$name received Beta-wrapped message")
    case _:SizeRequest => sender() ! onSizeRequest()
    case _ => throw new UnsupportedOperationException(s"$name received unknown message")
  }

  def onSizeRequest(): Long
} 
Example 9
Source File: RareBooks.scala    From reactive-application-development-scala   with Apache License 2.0 5 votes vote down vote up
package com.rarebooks.library

import akka.actor.{ Actor, ActorLogging, Props, Stash }
import akka.routing.{ ActorRefRoutee, Router, RoundRobinRoutingLogic }
import scala.concurrent.duration.{ MILLISECONDS => Millis, FiniteDuration, Duration }

object RareBooks {

  case object Close
  case object Open
  case object Report

  def props: Props =
    Props(new RareBooks)
}

class RareBooks extends Actor with ActorLogging with Stash {

  import context.dispatcher
  import RareBooks._
  import RareBooksProtocol._

  private val openDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.open-duration", Millis), Millis)

  private val closeDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.close-duration", Millis), Millis)

  private val nbrOfLibrarians: Int = context.system.settings.config getInt "rare-books.nbr-of-librarians"

  private val findBookDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.librarian.find-book-duration", Millis), Millis)

  var requestsToday: Int = 0
  var totalRequests: Int = 0

  var router: Router = createLibrarian()

  context.system.scheduler.scheduleOnce(openDuration, self, Close)

  
  protected def createLibrarian(): Router = {
    var cnt: Int = 0
    val routees: Vector[ActorRefRoutee] = Vector.fill(nbrOfLibrarians) {
      val r = context.actorOf(Librarian.props(findBookDuration), s"librarian-$cnt")
      cnt += 1
      ActorRefRoutee(r)
    }
    Router(RoundRobinRoutingLogic(), routees)
  }
} 
Example 10
Source File: Librarian.scala    From reactive-application-development-scala   with Apache License 2.0 5 votes vote down vote up
package com.rarebooks.library

import akka.actor.{ Actor, ActorRef, ActorLogging, Props, Stash }
import scala.concurrent.duration.FiniteDuration

object Librarian {

  import Catalog._
  import RareBooksProtocol._

  final case class Done(e: Either[BookNotFound, BookFound], customer: ActorRef)

  def props(findBookDuration: FiniteDuration): Props =
    Props(new Librarian(findBookDuration))

  
  private def process(r: Either[BookNotFound, BookFound], sender: ActorRef): Unit = {
    r fold (
      f => {
        sender ! f
        log.info(f.toString)
      },
      s => sender ! s)
  }
} 
Example 11
Source File: RareBooks.scala    From reactive-application-development-scala   with Apache License 2.0 5 votes vote down vote up
package com.rarebooks.library

import akka.actor.{Actor, ActorLogging, ActorPath, Address, OneForOneStrategy, Props, RootActorPath, Stash, SupervisorStrategy}
import akka.routing.{ActorRefRoutee, RoundRobinRoutingLogic, Router}

import scala.concurrent.duration.{Duration, FiniteDuration, MILLISECONDS => Millis}

object RareBooks {

  case object Close
  case object Open
  case object Report

//  val name: String =
//    "rare-books"
//
//  def pathFor(address: Address): ActorPath =
//    RootActorPath(address) / "user" / name
  
  def props: Props =
    Props(new RareBooks)
}

class RareBooks extends Actor with ActorLogging with Stash {

  import context.dispatcher
  import RareBooks._
  import LibraryProtocol._

  override val supervisorStrategy: SupervisorStrategy = {
    val decider: SupervisorStrategy.Decider = {
      case Librarian.ComplainException(complain, customer) =>
        customer ! Credit()
        log.info(s"RareBooks sent customer $customer a credit")
        SupervisorStrategy.Restart
    }
    OneForOneStrategy()(decider orElse super.supervisorStrategy.decider)
  }

  private val openDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.open-duration", Millis), Millis)

  private val closeDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.close-duration", Millis), Millis)

  private val nbrOfLibrarians: Int = context.system.settings.config getInt "rare-books.nbr-of-librarians"

  private val findBookDuration: FiniteDuration =
    Duration(context.system.settings.config.getDuration("rare-books.librarian.find-book-duration", Millis), Millis)

  private val maxComplainCount: Int = context.system.settings.config getInt "rare-books.librarian.max-complain-count"

  var requestsToday: Int = 0
  var totalRequests: Int = 0

  var router: Router = createLibrarian()

  context.system.scheduler.scheduleOnce(openDuration, self, Close)

  
  protected def createLibrarian(): Router = {
    var cnt: Int = 0
    val routees: Vector[ActorRefRoutee] = Vector.fill(nbrOfLibrarians) {
      val r = context.actorOf(Librarian.props(findBookDuration, maxComplainCount), s"librarian-$cnt")
      cnt += 1
      ActorRefRoutee(r)
    }
    Router(RoundRobinRoutingLogic(), routees)
  }
} 
Example 12
Source File: QueueActor.scala    From reliable-http-client   with Apache License 2.0 5 votes vote down vote up
package rhttpc.transport.inmem

import akka.pattern._
import akka.actor.{Actor, ActorLogging, ActorRef, Props, Stash}
import akka.routing.{RoundRobinRoutingLogic, Routee, Router}
import akka.util.Timeout
import rhttpc.transport.{Message, RejectingMessage}

import scala.concurrent.Future
import scala.concurrent.duration.FiniteDuration
import scala.util.control.NonFatal

private class QueueActor(consumeTimeout: FiniteDuration,
                         retryDelay: FiniteDuration) extends Actor with Stash with ActorLogging {

  import context.dispatcher

  private var consumers = Map.empty[ActorRef, AskingActorRefRouteeWithSpecifiedMessageType]

  private var router = Router(RoundRobinRoutingLogic(), collection.immutable.IndexedSeq.empty)

  override def receive: Receive = {
    case RegisterConsumer(consumer, fullMessage) =>
      val routee = AskingActorRefRouteeWithSpecifiedMessageType(consumer, consumeTimeout, handleResponse, fullMessage)
      consumers += consumer -> routee
      router = router.addRoutee(routee)
      log.debug(s"${self.path.name}: registered consumer, unstashing")
      unstashAll()
    case UnregisterConsumer(consumer) =>
      log.debug(s"${self.path.name}: unregistered consumer")
      consumers.get(consumer).foreach { routee =>
        consumers -= consumer
        router = router.removeRoutee(routee)
      }
      sender() ! ((): Unit)
    case msg: Message[_] =>
      if (consumers.isEmpty) {
        log.debug(s"${self.path.name}: got message when no consumer registered, stashing")
        stash()
        implicit val timeout = Timeout(consumeTimeout)
        sender() ! ((): Unit)
      } else {
        router.route(msg, sender())
      }
  }

  private def handleResponse(future: Future[Any], msg: Message[_]): Unit =
    future.recover {
      case ex: AskTimeoutException =>
        log.error(ex, s"${self.path.name}: REJECT [${msg.content.getClass.getName}] because of ask timeout")
      case ex: Exception with RejectingMessage =>
        log.error(ex, s"${self.path.name}: REJECT [${msg.content.getClass.getName}] because of rejecting failure")
      case NonFatal(ex) =>
        log.error(ex, s"${self.path.name}: will RETRY [${msg.content.getClass.getName}] after $retryDelay because of failure")
        context.system.scheduler.scheduleOnce(retryDelay, self, msg)
    }

}

object QueueActor {
  def props(consumeTimeout: FiniteDuration,
            retryDelay: FiniteDuration): Props = Props(
    new QueueActor(
      consumeTimeout = consumeTimeout,
      retryDelay = retryDelay))
}

private[inmem] case class AskingActorRefRouteeWithSpecifiedMessageType(ref: ActorRef,
                                                                       askTimeout: FiniteDuration,
                                                                       handleResponse: (Future[Any], Message[_]) => Unit,
                                                                       fullMessage: Boolean)
  extends Routee {

  override def send(message: Any, sender: ActorRef): Unit = {
    val typedMessage = message.asInstanceOf[Message[_]]
    val msgToSend = if (fullMessage) message else typedMessage.content
    handleResponse(ref.ask(msgToSend)(askTimeout, sender), typedMessage)
  }
}

private[inmem] case class RegisterConsumer(consumer: ActorRef, fullMessage: Boolean)

private[inmem] case class UnregisterConsumer(consumer: ActorRef) 
Example 13
Source File: Librarian.scala    From reactive-application-development-scala   with Apache License 2.0 5 votes vote down vote up
package com.rarebooks.library

import akka.actor.{ Actor, ActorRef, ActorLogging, Props, Stash }
import scala.concurrent.duration.FiniteDuration

object Librarian {

  import Catalog._
  import RareBooksProtocol._

  final case class Done(e: Either[BookNotFound, BookFound], customer: ActorRef)

  def props(findBookDuration: FiniteDuration): Props =
      Props(new Librarian(findBookDuration))

  
  private def process(r: Either[BookNotFound, BookFound], sender: ActorRef): Unit = {
    r fold (
      f => {
        sender ! f
        log.info(f.toString)
      },
      s => sender ! s)
  }
} 
Example 14
Source File: WebsocketSession.scala    From graphcool-framework   with Apache License 2.0 5 votes vote down vote up
package cool.graph.websockets

import java.util.concurrent.TimeUnit

import akka.actor.{Actor, ActorRef, PoisonPill, Props, ReceiveTimeout, Stash, Terminated}
import cool.graph.akkautil.{LogUnhandled, LogUnhandledExceptions}
import cool.graph.bugsnag.BugSnagger
import cool.graph.messagebus.QueuePublisher
import cool.graph.websockets.protocol.Request
import scala.collection.mutable
import scala.concurrent.duration._ // if you don't supply your own Protocol (see below)

object WebsocketSessionManager {
  object Requests {
    case class OpenWebsocketSession(projectId: String, sessionId: String, outgoing: ActorRef)
    case class CloseWebsocketSession(sessionId: String)

    case class IncomingWebsocketMessage(projectId: String, sessionId: String, body: String)
    case class IncomingQueueMessage(sessionId: String, body: String)
  }

  object Responses {
    case class OutgoingMessage(text: String)
  }
}

case class WebsocketSessionManager(
    requestsPublisher: QueuePublisher[Request],
    bugsnag: BugSnagger
) extends Actor
    with LogUnhandled
    with LogUnhandledExceptions {
  import WebsocketSessionManager.Requests._

  val websocketSessions = mutable.Map.empty[String, ActorRef]

  override def receive: Receive = logUnhandled {
    case OpenWebsocketSession(projectId, sessionId, outgoing) =>
      val ref = context.actorOf(Props(WebsocketSession(projectId, sessionId, outgoing, requestsPublisher, bugsnag)))
      context.watch(ref)
      websocketSessions += sessionId -> ref

    case CloseWebsocketSession(sessionId) =>
      websocketSessions.get(sessionId).foreach(context.stop)

    case req: IncomingWebsocketMessage =>
      websocketSessions.get(req.sessionId) match {
        case Some(session) => session ! req
        case None =>
          println(s"No session actor found for ${req.sessionId} | ${req.projectId} when processing websocket message. This should only happen very rarely.")
      }

    case req: IncomingQueueMessage =>
      websocketSessions.get(req.sessionId) match {
        case Some(session) => session ! req
        case None          => // Session already closed
      }

    case Terminated(terminatedActor) =>
      websocketSessions.retain {
        case (_, sessionActor) => sessionActor != terminatedActor
      }
  }
}

case class WebsocketSession(
    projectId: String,
    sessionId: String,
    outgoing: ActorRef,
    requestsPublisher: QueuePublisher[Request],
    bugsnag: BugSnagger
) extends Actor
    with LogUnhandled
    with LogUnhandledExceptions
    with Stash {
  import WebsocketSessionManager.Requests._
  import WebsocketSessionManager.Responses._
  import metrics.SubscriptionWebsocketMetrics._

  activeWsConnections.inc
  context.setReceiveTimeout(FiniteDuration(60, TimeUnit.MINUTES))

  def receive: Receive = logUnhandled {
    case IncomingWebsocketMessage(_, _, body) => requestsPublisher.publish(Request(sessionId, projectId, body))
    case IncomingQueueMessage(_, body)        => outgoing ! OutgoingMessage(body)
    case ReceiveTimeout                       => context.stop(self)
  }

  override def postStop = {
    activeWsConnections.dec
    outgoing ! PoisonPill
    requestsPublisher.publish(Request(sessionId, projectId, "STOP"))
  }
} 
Example 15
Source File: Counter.scala    From toketi-iothubreact   with MIT License 5 votes vote down vote up
// Copyright (c) Microsoft. All rights reserved.

package it.helpers

import java.util.concurrent.Executors

import akka.actor.{Actor, Stash}

import scala.concurrent.ExecutionContext


class Counter extends Actor with Stash {

  implicit val executionContext = ExecutionContext
    .fromExecutorService(Executors.newFixedThreadPool(sys.runtime.availableProcessors))

  private[this] var count: Long = 0

  override def receive: Receive = ready

  def ready: Receive = {
    case "reset" ⇒ {
      context.become(busy)
      count = 0
      context.become(ready)
      unstashAll()
    }
    case "inc"   ⇒ {
      context.become(busy)
      count += 1
      context.become(ready)
      unstashAll()
    }
    case "get"   ⇒ sender() ! count
  }

  def busy: Receive = {
    case _ ⇒ stash()
  }
} 
Example 16
Source File: Pipe.scala    From eclair   with Apache License 2.0 5 votes vote down vote up
package fr.acinq.eclair

import akka.actor.{Actor, ActorLogging, ActorRef, Stash}
import fr.acinq.eclair.channel.Commitments.msg2String
import fr.acinq.eclair.wire.LightningMessage


class Pipe extends Actor with Stash with ActorLogging {

  def receive = {
    case (a: ActorRef, b: ActorRef) =>
      unstashAll()
      context become connected(a, b)

    case _ => stash()
  }

  def connected(a: ActorRef, b: ActorRef): Receive = {
    case msg: LightningMessage if sender() == a =>
      log.debug(f"A ---${msg2String(msg)}%-6s--> B")
      b forward msg
    case msg: LightningMessage if sender() == b =>
      log.debug(f"A <--${msg2String(msg)}%-6s--- B")
      a forward msg
  }
} 
Example 17
Source File: FuzzyPipe.scala    From eclair   with Apache License 2.0 5 votes vote down vote up
package fr.acinq.eclair.channel

import akka.actor.{Actor, ActorLogging, ActorRef, Stash}
import fr.acinq.eclair.Features
import fr.acinq.eclair.channel.Commitments.msg2String
import fr.acinq.eclair.wire.{Init, LightningMessage}
import scodec.bits.ByteVector

import scala.concurrent.duration._
import scala.util.Random


class FuzzyPipe(fuzzy: Boolean) extends Actor with Stash with ActorLogging {

  import scala.concurrent.ExecutionContext.Implicits.global

  def receive = {
    case (a: ActorRef, b: ActorRef) =>
      unstashAll()
      context become connected(a, b, 10)

    case _ => stash()
  }

  def stayOrDisconnect(a: ActorRef, b: ActorRef, countdown: Int): Unit = {
    if (!fuzzy) context become connected(a, b, countdown - 1) // fuzzy mode disabled, we never disconnect
    else if (countdown > 1) context become connected(a, b, countdown - 1)
    else {
      log.debug("DISCONNECTED")
      a ! INPUT_DISCONNECTED
      b ! INPUT_DISCONNECTED
      context.system.scheduler.scheduleOnce(100 millis, self, 'reconnect)
      context become disconnected(a, b)
    }
  }

  def connected(a: ActorRef, b: ActorRef, countdown: Int): Receive = {
    case msg: LightningMessage if sender() == a =>
      log.debug(f"A ---${msg2String(msg)}%-6s--> B")
      b forward msg
      stayOrDisconnect(a, b, countdown)
    case msg: LightningMessage if sender() == b =>
      log.debug(f"A <--${msg2String(msg)}%-6s--- B")
      a forward msg
      stayOrDisconnect(a, b, countdown)
  }

  def disconnected(a: ActorRef, b: ActorRef): Receive = {
    case msg: LightningMessage if sender() == a =>
      // dropped
      log.info(f"A ---${msg2String(msg)}%-6s-X")
    case msg: LightningMessage if sender() == b =>
      // dropped
      log.debug(f"  X-${msg2String(msg)}%-6s--- B")
    case 'reconnect =>
      log.debug("RECONNECTED")
      val dummyInit = Init(Features.empty)
      a ! INPUT_RECONNECTED(self, dummyInit, dummyInit)
      b ! INPUT_RECONNECTED(self, dummyInit, dummyInit)
      context become connected(a, b, Random.nextInt(40))
  }
} 
Example 18
Source File: PausableActor.scala    From Akka-Cookbook   with MIT License 5 votes vote down vote up
package com.packt.chapter10

import akka.actor.{Actor, ActorLogging, ActorRef, Stash}
import com.packt.chapter10.PausableActor.{Ready, Work}

object PausableActor {
  case class Work(id: Int)
  case object Ready
}

class PausableActor(target: ActorRef) extends Actor with ActorLogging with Stash {
  def receive = {
    case work: Work =>
      target ! work
      log.info(s"Received Work [${work.id}]. Sending and pausing.")
      context.become(pausedBehavior, discardOld = false)
  }

  def pausedBehavior : Receive = {
    case work: Work =>
      stash()
    case Ready if sender == target =>
      log.info(s"[${target.path.name}] is ready again.")
      context.unbecome()
      unstashAll()
    case Ready =>
      log.info(s"Discarding [Ready] from other actor different from ${target.path.name}")
  }
} 
Example 19
Source File: JarStoreServer.scala    From incubator-retired-gearpump   with Apache License 2.0 5 votes vote down vote up
package org.apache.gearpump.jarstore

import akka.actor.{Actor, Stash}
import akka.pattern.pipe

import org.apache.gearpump.cluster.ClientToMaster.{GetJarStoreServer, JarStoreServerAddress}
import org.apache.gearpump.util._

class JarStoreServer(jarStoreRootPath: String) extends Actor with Stash {
  private val host = context.system.settings.config.getString(Constants.GEARPUMP_HOSTNAME)
  private val jarStore = JarStore.get(jarStoreRootPath)
  jarStore.init(context.system.settings.config)
  private val server = new FileServer(context.system, host, 0, jarStore)
  implicit val timeout = Constants.FUTURE_TIMEOUT
  implicit val executionContext = context.dispatcher

  server.start pipeTo self

  def receive: Receive = {
    case FileServer.Port(port) =>
      context.become(listen(port))
      unstashAll()
    case _ =>
      stash()
  }

  def listen(port: Int): Receive = {
    case GetJarStoreServer =>
      sender ! JarStoreServerAddress(s"http://$host:$port/")
  }

  override def postStop(): Unit = {
    server.stop
  }
} 
Example 20
Source File: TrafficGenerator.scala    From trucking-iot   with Apache License 2.0 5 votes vote down vote up
package com.orendainx.trucking.simulator.generators

import java.time.Instant

import akka.actor.{ActorLogging, ActorRef, Props, Stash}
import com.orendainx.trucking.commons.models._
import com.orendainx.trucking.simulator.coordinators.GeneratorCoordinator
import com.orendainx.trucking.simulator.depots.ResourceDepot.{RequestRoute, ReturnRoute}
import com.orendainx.trucking.simulator.generators.DataGenerator.{GenerateData, NewResource}
import com.orendainx.trucking.simulator.models._
import com.orendainx.trucking.simulator.transmitters.DataTransmitter.Transmit
import com.orendainx.trucking.simulator.models.{EmptyRoute, Route}
import com.typesafe.config.Config

import scala.collection.mutable
import scala.util.Random


  def props(depot: ActorRef, flowManager: ActorRef)(implicit config: Config) =
    Props(new TrafficGenerator(depot, flowManager))
}

class TrafficGenerator(depot: ActorRef, flowManager: ActorRef)(implicit config: Config) extends DataGenerator with Stash with ActorLogging {

  // Some settings
  val NumberOfRoutes = config.getInt("generator.routes-to-simulate")
  val CongestionDelta = config.getInt("generator.congestion.delta")

  var congestionLevel = config.getInt("generator.congestion.start")
  var routes = mutable.Buffer.empty[Route]

  // Request NumberOfRoutes routes
  (1 to NumberOfRoutes).foreach(_ => depot ! RequestRoute(EmptyRoute))

  context become waitingOnDepot

  def waitingOnDepot: Receive = {
    case NewResource(newRoute: Route) =>
      routes += newRoute
      unstashAll()
      context become driverActive
      log.info(s"Received new route: ${newRoute.name}")

    case GenerateData =>
      stash()
      log.debug("Received Tick command while waiting on route. Command stashed for later processing.")
  }

  def driverActive: Receive = {
    case GenerateData =>
      routes.foreach { route =>
        // Create traffic data and emit it
        congestionLevel += -CongestionDelta + Random.nextInt(CongestionDelta*2 + 1)
        val traffic = TrafficData(Instant.now().toEpochMilli, route.id, congestionLevel)
        flowManager ! Transmit(traffic)
      }

      // Tell the coordinator we've acknowledged the drive command
      sender() ! GeneratorCoordinator.AcknowledgeTick(self)
  }

  def receive = {
    case _ => log.error("This message should never be seen.")
  }

  // When this actor is stopped, release resources it may still be holding onto
  override def postStop(): Unit =
    routes.foreach(ReturnRoute)
} 
Example 21
Source File: NoSharingDepot.scala    From trucking-iot   with Apache License 2.0 5 votes vote down vote up
package com.orendainx.trucking.simulator.depots

import akka.actor.{ActorLogging, Props, Stash}
import com.orendainx.trucking.simulator.depots.ResourceDepot.{RequestRoute, RequestTruck, ReturnRoute, ReturnTruck}
import com.orendainx.trucking.simulator.generators.DataGenerator.NewResource
import com.orendainx.trucking.simulator.models._
import com.orendainx.trucking.simulator.services.RouteParser
import com.orendainx.trucking.simulator.models.EmptyRoute
import com.typesafe.config.Config

import scala.util.Random


object NoSharingDepot {

  def props()(implicit config: Config) =
    Props(new NoSharingDepot())
}

class NoSharingDepot(implicit config: Config) extends ResourceDepot with Stash with ActorLogging {

  private val trucksAvailable = Random.shuffle(1 to config.getInt("resource-depot.trucks-available")).toList.map(Truck).toBuffer
  private val routesAvailable = RouteParser(config.getString("resource-depot.route-directory")).routes.toBuffer

  log.info("Trucks and routes initialized and ready for deployment")
  log.info(s"${trucksAvailable.length} trucks available.")
  log.info(s"${routesAvailable.length} routes available.")

  def receive = {
    case RequestTruck(previous) if previous != EmptyTruck =>
      val ind = trucksAvailable.indexWhere(_ != previous)
      if (ind >= 0) sender() ! NewResource(trucksAvailable.remove(ind))
      else stash() // None available, stash request for later

    case RequestTruck(_) =>
      if (trucksAvailable.nonEmpty) sender() ! NewResource(trucksAvailable.remove(0))
      else stash()

    case RequestRoute(previous) if previous != EmptyRoute =>
      val ind = routesAvailable.indexWhere(_ != previous)
      if (ind >= 0) sender() ! NewResource(routesAvailable.remove(ind))
      else stash()

    case RequestRoute(_) =>
      if (routesAvailable.nonEmpty) sender() ! NewResource(routesAvailable.remove(0))
      else stash()

    case ReturnTruck(truck) =>
      trucksAvailable.append(truck)
      unstashAll()

    case ReturnRoute(route) =>
      routesAvailable.append(route)
      unstashAll()
  }
} 
Example 22
Source File: InitializingActor.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.core.akka

import akka.actor.{Actor, ActorRef, ReceiveTimeout, Stash}
import akka.pattern.pipe
import hydra.common.config.ActorConfigSupport
import hydra.common.logging.LoggingAdapter
import hydra.core.HydraException
import hydra.core.akka.InitializingActor.{InitializationError, Initialized}
import hydra.core.protocol.HydraMessage
import retry.Success

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.control.NonFatal

trait InitializingActor
    extends Actor
    with ActorConfigSupport
    with Stash
    with LoggingAdapter {

  
  def initializationError(ex: Throwable): Receive
}

object InitializingActor {

  case object Initialized extends HydraMessage

  case class InitializationError(cause: Throwable) extends HydraMessage

}

@SerialVersionUID(1L)
class ActorInitializationException(
    ingestor: ActorRef,
    message: String,
    cause: Throwable
) extends HydraException(
      ActorInitializationException.enrichedMessage(ingestor, message),
      cause
    ) {
  def getActor: ActorRef = ingestor
}

object ActorInitializationException {

  private def enrichedMessage(actor: ActorRef, message: String) =
    Option(actor).map(a => s"${a.path}: $message").getOrElse(message)

  private[hydra] def apply(
      actor: ActorRef,
      message: String,
      cause: Throwable = null
  ) =
    new ActorInitializationException(actor, message, cause)

  def unapply(
      ex: ActorInitializationException
  ): Option[(ActorRef, String, Throwable)] =
    Some((ex.getActor, ex.getMessage, ex.getCause))
}