pekko/akka-patterns/src/main/scala/Patterns.scala

76 lines
2.2 KiB
Scala
Raw Normal View History

package se.scalablesolutions.akka.patterns
2010-02-13 21:45:35 +01:00
import se.scalablesolutions.akka.actor.Actor
object Patterns {
type PF[A, B] = PartialFunction[A, B]
2010-02-13 21:45:35 +01:00
/**
* Creates a new PartialFunction whose isDefinedAt is a combination
* of the two parameters, and whose apply is first to call filter.apply and then filtered.apply
*/
def filter[A, B](filter: PF[A, Unit], filtered: PF[A, B]): PF[A, B] = {
case a: A if filtered.isDefinedAt(a) && filter.isDefinedAt(a) =>
2010-02-13 21:45:35 +01:00
filter(a)
filtered(a)
}
/**
* Interceptor is a filter(x,y) where x.isDefinedAt is considered to be always true
*/
2010-03-17 17:48:46 +01:00
def intercept[A, B](interceptor: (A) => Unit, interceptee: PF[A, B]): PF[A, B] =
filter({case a if a.isInstanceOf[A] => interceptor(a)}, interceptee)
2010-02-13 21:45:35 +01:00
//FIXME 2.8, use default params with CyclicIterator
def loadBalancerActor(actors: => InfiniteIterator[Actor]): Actor = new Actor with LoadBalancer {
2010-02-13 21:45:35 +01:00
val seq = actors
}
2010-03-17 17:48:46 +01:00
def dispatcherActor(routing: PF[Any, Actor], msgTransformer: (Any) => Any): Actor =
new Actor with Dispatcher {
override def transform(msg: Any) = msgTransformer(msg)
2010-02-13 21:45:35 +01:00
def routes = routing
}
def dispatcherActor(routing: PF[Any, Actor]): Actor = new Actor with Dispatcher {
def routes = routing
2010-02-13 21:45:35 +01:00
}
2010-03-17 17:48:46 +01:00
def loggerActor(actorToLog: Actor, logger: (Any) => Unit): Actor =
dispatcherActor({case _ => actorToLog}, logger)
2010-02-13 21:45:35 +01:00
}
2010-03-17 17:48:46 +01:00
trait Dispatcher { self: Actor =>
2010-02-13 21:45:35 +01:00
protected def transform(msg: Any): Any = msg
protected def routes: PartialFunction[Any, Actor]
protected def dispatch: PartialFunction[Any, Unit] = {
2010-03-17 17:48:46 +01:00
case a if routes.isDefinedAt(a) =>
if (self.sender.isDefined) routes(a) forward transform(a)
2010-03-30 23:58:50 +02:00
else routes(a) ! transform(a)
2010-02-13 21:45:35 +01:00
}
def receive = dispatch
}
2010-03-17 17:48:46 +01:00
trait LoadBalancer extends Dispatcher { self: Actor =>
protected def seq: InfiniteIterator[Actor]
2010-02-13 21:45:35 +01:00
2010-03-17 17:48:46 +01:00
protected def routes = { case x if seq.hasNext => seq.next }
2010-02-13 21:45:35 +01:00
}
trait InfiniteIterator[T] extends Iterator[T]
class CyclicIterator[T](items: List[T]) extends InfiniteIterator[T] {
@volatile private[this] var current: List[T] = items
2010-02-13 21:45:35 +01:00
def hasNext = items != Nil
2010-02-13 21:45:35 +01:00
def next = {
val nc = if (current == Nil) items else current
2010-02-13 21:45:35 +01:00
current = nc.tail
nc.head
}
}