Permalink
Browse files

[reactivemongo] Combinator `orElse` for the handlers

  • Loading branch information...
cchantep
cchantep committed Oct 25, 2016
1 parent 46fff30 commit ff3d73226efd3efb6f5091cdc5d6f6cc90361618
@@ -19,7 +19,7 @@ sealed trait ConnectionHandler { self ⇒
*
* @param handler Query handler
*/
def withQueryHandler[T](handler: T)(implicit f: T QueryHandler) =
final def withQueryHandler[T](handler: T)(implicit f: T QueryHandler) =
ConnectionHandler(new QueryHandler {
def apply(cid: Int, q: Request) =
self.queryHandler(cid, q).orElse(f(handler)(cid, q))
@@ -31,11 +31,25 @@ sealed trait ConnectionHandler { self ⇒
*
* @param handler Write handler
*/
def withWriteHandler[T](handler: T)(implicit f: T WriteHandler) =
final def withWriteHandler[T](handler: T)(implicit f: T WriteHandler) =
ConnectionHandler(queryHandler, new WriteHandler {
def apply(cid: Int, op: WriteOp, w: Request) =
self.writeHandler(cid, op, w).orElse(f(handler)(cid, op, w))
})
/**
* Returns a new connection handler that first try this one,
* or else if it doesn't match, use the other one.
*
* {{{
* val connectionHandler3 = connectionHandler1 orElse connectionHandler2
* }}}
*/
final def orElse(other: ConnectionHandler): ConnectionHandler =
new ConnectionHandler {
val queryHandler = self.queryHandler orElse other.queryHandler
val writeHandler = self.writeHandler orElse other.writeHandler
}
}
/** Companion object for connection handler. */
@@ -68,11 +82,26 @@ object ConnectionHandler {
/** Query handler. */
sealed trait QueryHandler extends ((Int, Request) Option[Try[Response]]) {
self
/**
* @param channelId ID of channel
* @param query Query to respond to
*/
override def apply(channelId: Int, query: Request): Option[Try[Response]]
/**
* Returns a new query handler that first try this one,
* or else if it doesn't match, use the other one.
*
* {{{
* val queryHandler3 = queryHandler1 orElse queryHandler2
* }}}
*/
final def orElse(other: QueryHandler): QueryHandler = new QueryHandler {
def apply(channelId: Int, query: Request): Option[Try[Response]] =
self(channelId, query).orElse(other(channelId, query))
}
}
/** Query handler companion. */
@@ -106,7 +135,7 @@ object QueryHandler {
/** Write handler. */
sealed trait WriteHandler
extends ((Int, WriteOp, Request) Option[Try[Response]]) {
extends ((Int, WriteOp, Request) Option[Try[Response]]) { self
/**
* @param channelId ID of channel
@@ -115,6 +144,17 @@ sealed trait WriteHandler
*/
override def apply(channelId: Int, op: WriteOp, req: Request): Option[Try[Response]]
/**
* Returns a new write handler that first try this one,
* or else if it doesn't match, use the other one.
*
* {{{
* val writeHandler3 = writeHandler1 orElse writeHandler2
* }}}
*/
final def orElse(other: WriteHandler): WriteHandler = new WriteHandler {
def apply(channelId: Int, op: WriteOp, req: Request): Option[Try[Response]] = self(channelId, op, req).orElse(other(channelId, op, req))
}
}
/** Write handler companion. */
@@ -36,8 +36,7 @@ class ConnectionHandlerSpec extends org.specs2.mutable.Specification
ConnectionHandler(h).queryHandler(1, query1).
aka("query result #1") must beSome and (
handler.queryHandler(1, query1) aka "query result #2" must beNone
).
and(handler.withQueryHandler(h).queryHandler(1, query1).
).and(handler.withQueryHandler(h).queryHandler(1, query1).
aka("query result #3") must beSome)
}
@@ -46,6 +45,26 @@ class ConnectionHandlerSpec extends org.specs2.mutable.Specification
_: Request QueryResponse(None)
}).queryHandler(1, query1) aka "query result" must beNone
}
"be combined with orElse #1" in {
ConnectionHandler({
_: Request QueryResponse(BSONDocument("a" "b"))
}).orElse(ConnectionHandler { _: Request QueryResponse.empty }).
queryHandler(1, query1) aka "query result" must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("a", BSONString("b")) :: Nil) :: Nil ok
}
)
}
"be combined with orElse #2" in {
ConnectionHandler({ _: Request QueryResponse.empty }).
orElse(ConnectionHandler { _: Request
QueryResponse(BSONDocument("a" "b"))
}).queryHandler(1, query1) aka "query result" must beSome.which(
_ aka "response" must beResponse { case res if res.isEmpty ok }
)
}
}
"Handler with write handler" should {
@@ -71,6 +90,22 @@ class ConnectionHandlerSpec extends org.specs2.mutable.Specification
(_: WriteOp, _: Request) WriteResponse(None)
}).writeHandler(1, write1._1, write1._2) aka "write result" must beNone
}
"be combined using orElse" in {
val handler: ConnectionHandler = ConnectionHandler({
_: Request QueryResponse(BSONDocument("a" "b"))
})
ConnectionHandler(writeHandler = {
(_: WriteOp, _: Request) WriteResponse.successful(1, false)
})
handler.queryHandler(1, query1) aka "query result" must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("a", BSONString("b")) :: Nil) :: Nil ok
}
)
}
}
"Complete handler" should {
@@ -57,6 +57,17 @@ class QueryHandlerSpec extends org.specs2.mutable.Specification
case h h(1, query1) must beNone
}
}
"be combined using orElse" in {
QueryHandler { _ QueryResponse.successful(BSONDocument("foo" 1)) }.
orElse(QueryHandler.empty) must beLike {
case h h(1, query1) must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("foo", BSONInteger(1)) :: Nil) :: Nil ok
}
)
}
}
}
"Empty handler" should {
@@ -65,6 +76,18 @@ class QueryHandlerSpec extends org.specs2.mutable.Specification
case h h(1, query1) must beNone
}
}
"be combined using orElse" in {
QueryHandler.empty.orElse(QueryHandler { _
QueryResponse.successful(BSONDocument("foo" 1))
}) aka "query handler" must beLike {
case h h(1, query1) must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("foo", BSONInteger(1)) :: Nil) :: Nil ok
}
)
}
}
}
"Mixed handler" should {
@@ -71,6 +71,17 @@ class WriteHandlerSpec extends org.specs2.mutable.Specification
case h h(1, write1._1, write1._2) must beNone
}
}
"be combined using orElse" in {
WriteHandler { (_, _) WriteResponse(1 true) }.
orElse(WriteHandler.empty) must beLike {
case h h(1, write1._1, write1._2) must beSome.which(
_ aka "response" must beResponse {
_ aka "response" must beWriteSuccess(1, true)
}
)
}
}
}
"Empty handler" should {
@@ -79,6 +90,18 @@ class WriteHandlerSpec extends org.specs2.mutable.Specification
case h h(1, write1._1, write1._2) must beNone
}
}
"be combined using orElse" in {
WriteHandler.empty.orElse(
WriteHandler { (_, _) WriteResponse(1 true) }
) must beLike {
case h h(1, write1._1, write1._2) must beSome.which(
_ aka "response" must beResponse {
_ aka "response" must beWriteSuccess(1, true)
}
)
}
}
}
"Mixed handler" should {

0 comments on commit ff3d732

Please sign in to comment.