Permalink
Browse files

[reactivemongo] Update count in WriteResponse

  • Loading branch information...
cchantep
cchantep committed Sep 16, 2014
1 parent 1f71414 commit 23517d9db23b4e815205196166fd57a1fcff7351
View
@@ -169,9 +169,9 @@ val error2 = WriteResponse("Error #1") // equivalent
val error3 = WriteResponse.failed("Error #2", 1/* code */)
val error4 = WriteResponse("Error #2" -> 1/* code */) // equivalent
val success1 = WriteResponse(true/* updatedExisting */)
val success2 = WriteResponse.successful(true) // equivalent
val success3 = WriteResponse() // = WriteResponse.successful(false)
val success1 = WriteResponse(1/* update count */ -> true/* updatedExisting */)
val success2 = WriteResponse.successful(1, true) // equivalent
val success3 = WriteResponse() // = WriteResponse.successful(0, false)
```
When a handler supports some write cases, but not other, it can return an undefined response, to let the chance other handlers would manage it.
@@ -49,17 +49,18 @@ object MongoDB {
*/
def WriteError(channelId: Int, error: String, code: Option[Int] = None): Try[Response] = mkResponse(channelId, 4 /* unspecified */ , List(
BSONDocument("ok" -> 0, "err" -> error, "errmsg" -> error,
"code" -> code.getOrElse(-1)
/*, "n" -> 0, "updatedExisting" -> false */ )))
"code" -> code.getOrElse(-1), "updatedExisting" -> false, "n" -> 0)))
/**
* Builds a response for a successful write operation.
*
* @param channelId Unique ID of channel
* @param count The number of documents affected by last command, 0 if none
* @param updatedExisting Some existing document has been updated
*/
def WriteSuccess(channelId: Int, updatedExisting: Boolean = false): Try[Response] = mkResponse(channelId, 4 /*unspecified*/ , List(
BSONDocument("ok" -> 1, "updatedExisting" -> updatedExisting)))
def WriteSuccess(channelId: Int, count: Int, updatedExisting: Boolean = false): Try[Response] = mkResponse(channelId, 4 /*unspecified*/ ,
List(BSONDocument(
"ok" -> 1, "updatedExisting" -> updatedExisting, "n" -> count)))
/**
* Builds a Mongo response.
@@ -30,9 +30,11 @@ object WriteResponse {
/**
* Factory for successful response.
*
* @param count The number of documents affected by last command, 0 if none
* @param updatedExisting Some existing document has been updated
*/
def successful(updatedExisting: Boolean = false) = apply(updatedExisting)
def successful(count: Int = 0, updatedExisting: Boolean = false) =
apply(count -> updatedExisting)
/**
* Empty/undefined response, returned by handler no supporting
@@ -23,11 +23,11 @@ object WriteResponseMaker {
* {{{
* import acolyte.reactivemongo.WriteResponseMaker
*
* val maker = implicitly[WriteResponseMaker[Boolean]]
* val maker = implicitly[WriteResponseMaker[(Int, Boolean)]]
* }}}
*/
implicit def SuccessWriteResponseMaker = new WriteResponseMaker[Boolean] {
def apply(channelId: Int, updatedExisting: Boolean): Option[Try[Response]] = Some(MongoDB.WriteSuccess(channelId, updatedExisting))
implicit def SuccessWriteResponseMaker = new WriteResponseMaker[(Int, Boolean)] {
def apply(channelId: Int, up: (Int, Boolean)): Option[Try[Response]] = Some(MongoDB.WriteSuccess(channelId, up._1, up._2))
}
/**
@@ -38,7 +38,7 @@ object WriteResponseMaker {
* }}}
*/
implicit def UnitWriteResponseMaker = new WriteResponseMaker[Unit] {
def apply(channelId: Int, effect: Unit): Option[Try[Response]] = Some(MongoDB.WriteSuccess(channelId, false))
def apply(channelId: Int, effect: Unit): Option[Try[Response]] = Some(MongoDB.WriteSuccess(channelId, 0, false))
}
/**
@@ -9,7 +9,8 @@ import reactivemongo.bson.{
}
object ConnectionHandlerSpec extends org.specs2.mutable.Specification
with QueryHandlerFixtures with WriteHandlerFixtures with ResponseMatchers {
with QueryHandlerFixtures with WriteHandlerFixtures
with ConnectionHandlerFixtures with ResponseMatchers {
"Connection handler" title
@@ -68,53 +69,59 @@ object ConnectionHandlerSpec extends org.specs2.mutable.Specification
}
"Complete handler" should {
val handler = ConnectionHandler(QueryHandler {
case RequestBody("test1", _) QueryResponse(BSONDocument("b" -> 3))
case RequestBody("test2", _) QueryResponse(
Seq(BSONDocument("d" -> 4.56d), BSONDocument("ef" -> "ghi")))
case _ QueryResponse(None)
}, WriteHandler {
case (DeleteOp, _) WriteResponse("Error #2")
case (InsertOp, _) WriteResponse()
case _ WriteResponse(None)
})
"return expected query result #1" in {
handler.queryHandler(1, query1) aka "query result" must beSome.which(
chandler1.queryHandler(1, query1) aka "query result" must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("b", BSONInteger(3)) :: Nil) :: Nil ok
})
}
"return expected query result #2" in {
handler.queryHandler(2, query2) aka "query result" must beSome.which(
chandler1.queryHandler(2, query2) aka "query result" must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("d", BSONDouble(4.56d)) :: Nil) ::
ValueDocument(("ef", BSONString("ghi")) :: Nil) :: Nil ok
})
}
"return no query result" in {
handler.queryHandler(3, query3) aka "query handler" must beNone
chandler1.queryHandler(3, query3) aka "query handler" must beNone
}
"return expected write result #1" in {
handler.writeHandler(1, write1._1, write1._2).
chandler1.writeHandler(1, write1._1, write1._2).
aka("write result") must beSome.which(
_ aka "response" must beWriteError("Error #2"))
}
"return expected write result #2" in {
handler.writeHandler(2, write2._1, write2._2).
chandler1.writeHandler(2, write2._1, write2._2).
aka("write result") must beSome.which(_ aka "response" must beResponse {
case ValueDocument(("ok", BSONInteger(1)) ::
("updatedExisting", BSONBoolean(false)) :: Nil) :: Nil ok
("updatedExisting", BSONBoolean(false)) ::
("n", BSONInteger(0)) :: Nil) :: Nil ok
})
}
"return no write result" in {
handler.writeHandler(3, write3._1, write3._2).
chandler1.writeHandler(3, write3._1, write3._2).
aka("write result") must beNone
}
}
}
trait ConnectionHandlerFixtures {
fixtures: QueryHandlerFixtures with WriteHandlerFixtures
lazy val chandler1 = ConnectionHandler(QueryHandler {
case RequestBody(col, _) if col.endsWith("test1")
QueryResponse(BSONDocument("b" -> 3))
case RequestBody(col, _) if col.endsWith("test2") QueryResponse(
Seq(BSONDocument("d" -> 4.56d), BSONDocument("ef" -> "ghi")))
case q QueryResponse(None)
}, WriteHandler {
case (DeleteOp, _) WriteResponse("Error #2")
case (InsertOp, _) WriteResponse()
case _ WriteResponse(None)
})
}
@@ -97,14 +97,14 @@ object MongoDBSpec extends org.specs2.mutable.Specification with MongoFixtures {
"Response to write success" should {
"contain expected BSON when no existing document was updated" in {
MongoDB.WriteSuccess(5) aka "response" must beSuccessfulTry.
MongoDB.WriteSuccess(5, 1) aka "response" must beSuccessfulTry.
which(Response.parse(_).toList aka "response" must beLike {
case doc :: Nil doc aka "success" must_== doc6
})
}
"contain expected BSON when existing document was updated" in {
MongoDB.WriteSuccess(5, true) aka "response" must beSuccessfulTry.
MongoDB.WriteSuccess(5, 2, true) aka "response" must beSuccessfulTry.
which(Response.parse(_).toList aka "response" must beLike {
case doc :: Nil doc aka "success" must_== doc7
})
@@ -129,13 +129,15 @@ private[reactivemongo] trait MongoFixtures {
"title" -> "Title", "modified" -> BSONDateTime(System.currentTimeMillis))
val doc4 = BSONDocument("ok" -> 0, "err" -> "Write Error #1",
"errmsg" -> "Write Error #1", "code" -> -1)
"errmsg" -> "Write Error #1", "code" -> -1,
"updatedExisting" -> false, "n" -> 0)
val doc5 = BSONDocument("ok" -> 0, "err" -> "Write Error #2",
"errmsg" -> "Write Error #2", "code" -> 3)
"errmsg" -> "Write Error #2", "code" -> 3,
"updatedExisting" -> false, "n" -> 0)
val doc6 = BSONDocument("ok" -> 1, "updatedExisting" -> false)
val doc7 = BSONDocument("ok" -> 1, "updatedExisting" -> true)
val doc6 = BSONDocument("ok" -> 1, "updatedExisting" -> false, "n" -> 1)
val doc7 = BSONDocument("ok" -> 1, "updatedExisting" -> true, "n" -> 2)
@inline def bson(d: BSONDocument) = d.elements.toList
}
@@ -48,10 +48,10 @@ object ResponseMakerSpec
"Write response maker" should {
"be a successful one for boolean (updatedExisting)" in {
val makr = implicitly[WriteResponseMaker[Boolean]]
val makr = implicitly[WriteResponseMaker[(Int, Boolean)]]
makr(4, true) aka "response" must beSome.which { prepared
zip(prepared, MongoDB.WriteSuccess(4, true)).
makr(4, 1 -> true) aka "response" must beSome.which { prepared
zip(prepared, MongoDB.WriteSuccess(4, 1, true)).
aka("maker") must beSuccessfulTry.like {
case (a, b) a.documents aka "response" must_== b.documents
}
@@ -62,7 +62,7 @@ object ResponseMakerSpec
val makr = implicitly[WriteResponseMaker[Unit]]
makr(4, ()) aka "response" must beSome.which { prepared
zip(prepared, MongoDB.WriteSuccess(4, false)).
zip(prepared, MongoDB.WriteSuccess(4, 0, false)).
aka("maker") must beSuccessfulTry.like {
case (a, b) a.documents aka "response" must_== b.documents
}
@@ -5,7 +5,7 @@ import scala.util.Try
import org.specs2.mutable.Specification
import org.specs2.matcher.{ Expectable, Matcher, MatchResult }
import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONString }
import reactivemongo.bson.{ BSONBoolean, BSONDocument, BSONInteger, BSONString }
import reactivemongo.core.protocol.Response
trait ResponseMatchers { specs: Specification
@@ -44,8 +44,11 @@ trait ResponseMatchers { specs: Specification ⇒
e.value aka "prepared" must beSuccessfulTry.which {
Response.parse(_).toList aka "response" must beLike {
case ValueDocument(("ok", BSONInteger(0)) ::
("err", BSONString(err)) :: ("errmsg", BSONString(errmsg)) ::
("code", BSONInteger(c)) :: Nil) :: Nil
("err", BSONString(err)) ::
("errmsg", BSONString(errmsg)) ::
("code", BSONInteger(c)) ::
("updatedExisting", BSONBoolean(false)) ::
("n", BSONInteger(0)) :: Nil) :: Nil
err aka "error message (err)" must_== msg and (
errmsg aka "error message (errmsg)" must_== msg) and (
c aka "error code" must_== code.getOrElse(-1))
@@ -10,25 +10,27 @@ object WriteHandlerSpec extends org.specs2.mutable.Specification
"Handler" should {
"return a success response with existing document updated" in {
implicitly[WriteHandler]({
(_: WriteOp, _: Request) WriteResponse(true)
(_: WriteOp, _: Request) WriteResponse(1 -> true)
}) aka "write handler" must beLike {
case h h(1, write1._1, write1._2) must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("ok", BSONInteger(k)) ::
("updatedExisting", BSONBoolean(up)) :: Nil) :: Nil
("updatedExisting", BSONBoolean(up)) ::
("n", BSONInteger(1)) :: Nil) :: Nil
k aka "ok" must_== 1 and (up aka "updated existing" must beTrue)
})
}
}
"return a success response without existing document updated" in {
implicitly[WriteHandler]({
(_: WriteOp, _: Request) WriteResponse(false)
(_: WriteOp, _: Request) WriteResponse(0 -> false)
}) aka "write handler" must beLike {
case h h(1, write1._1, write1._2) must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("ok", BSONInteger(k)) ::
("updatedExisting", BSONBoolean(up)) :: Nil) :: Nil
("updatedExisting", BSONBoolean(up)) ::
("n", BSONInteger(0)) :: Nil) :: Nil
k aka "ok" must_== 1 and (up aka "updated existing" must beFalse)
})
}
@@ -41,7 +43,8 @@ object WriteHandlerSpec extends org.specs2.mutable.Specification
case h h(1, write1._1, write1._2) must beSome.which(
_ aka "response" must beResponse {
case ValueDocument(("ok", BSONInteger(k)) ::
("updatedExisting", BSONBoolean(up)) :: Nil) :: Nil
("updatedExisting", BSONBoolean(up)) ::
("n", BSONInteger(0)) :: Nil) :: Nil
k aka "ok" must_== 1 and (up aka "updated existing" must beFalse)
})
}
@@ -60,9 +63,9 @@ object WriteHandlerSpec extends org.specs2.mutable.Specification
implicitly[WriteHandler]({ (_: WriteOp, _: Request)
WriteResponse("Error message #2", 7)
}) aka "write handler" must beLike {
case h h(2, write1._1, write1._2) must beSome.which(
_ aka "response" must beWriteError("Error message #2", Some(7)))
}
case h h(2, write1._1, write1._2) must beSome.which(
_ aka "response" must beWriteError("Error message #2", Some(7)))
}
}
"return no response" in {
@@ -87,7 +90,7 @@ object WriteHandlerSpec extends org.specs2.mutable.Specification
(op, req) match {
case (DeleteOp, RequestBody("test1", _)) WriteResponse.empty
case (InsertOp, RequestBody("test2", _)) WriteResponse("Error #2")
case (UpdateOp, RequestBody("test3", _)) WriteResponse(true)
case (UpdateOp, RequestBody("test3", _)) WriteResponse(2, true)
case (_, RequestBody("test4", _)) WriteResponse.successful()
}
}
@@ -109,8 +112,9 @@ object WriteHandlerSpec extends org.specs2.mutable.Specification
handler aka "mixed handler" must beLike {
case h h(3, write3._1, write3._2) aka "prepared" must beSome.which(
_ aka "write response" must beResponse {
case ValueDocument(("ok", BSONInteger(1)) ::
("updatedExisting", BSONBoolean(true)) :: Nil) :: Nil ok
case ValueDocument(("ok", BSONInteger(1)) ::
("updatedExisting", BSONBoolean(true)) ::
("n", BSONInteger(2)) :: Nil) :: Nil ok
})
}
}
@@ -44,21 +44,23 @@ object WriteResponseSpec
"be made for successful result" >> {
"with a boolean updatedExisting flag" in {
WriteResponse(true) aka "prepared" must beLike {
WriteResponse(1 -> true) aka "prepared" must beLike {
case prepared prepared(3) aka "applied" must beSome.which(
_ aka "write response" must beResponse {
case ValueDocument(("ok", BSONInteger(1)) ::
("updatedExisting", BSONBoolean(true)) :: Nil) :: Nil ok
("updatedExisting", BSONBoolean(true)) ::
("n", BSONInteger(1)) :: Nil) :: Nil ok
})
}
}
"with a boolean updatedExisting flag using named factory" in {
WriteResponse.successful(false) aka "prepared" must beLike {
WriteResponse.successful(0, false) aka "prepared" must beLike {
case prepared prepared(3) aka "applied" must beSome.which(
_ aka "write response" must beResponse {
case ValueDocument(("ok", BSONInteger(1)) ::
("updatedExisting", BSONBoolean(false)) :: Nil) :: Nil ok
("updatedExisting", BSONBoolean(false)) ::
("n", BSONInteger(0)) :: Nil) :: Nil ok
})
}
}
@@ -68,7 +70,8 @@ object WriteResponseSpec
case prepared prepared(4) aka "applied" must beSome.which(
_ aka "write response" must beResponse {
case ValueDocument(("ok", BSONInteger(1)) ::
("updatedExisting", BSONBoolean(false)) :: Nil) :: Nil ok
("updatedExisting", BSONBoolean(false)) ::
("n", BSONInteger(0)) :: Nil) :: Nil ok
})
}
}
@@ -78,7 +81,8 @@ object WriteResponseSpec
case prepared prepared(4) aka "applied" must beSome.which(
_ aka "write response" must beResponse {
case ValueDocument(("ok", BSONInteger(1)) ::
("updatedExisting", BSONBoolean(false)) :: Nil) :: Nil ok
("updatedExisting", BSONBoolean(false)) ::
("n", BSONInteger(0)) :: Nil) :: Nil ok
})
}
}

0 comments on commit 23517d9

Please sign in to comment.