Deleted couchbase document seems visible to update but not get - memcached

When trying to update a couchbase document that was previously deleted the update call fails with a CASResponse.EXISTS code rather than a CASResponse.NOT_FOUND. However a call to get the previously deleted key immediately after the delete is complete returns null as expected:
def main(args: Array[String]){
val uris = List(URI.create("http://localhost:8091/pools"))
val client = new CouchbaseClient(uris, "test", "password")
client.add("asdf", "qwer").get
client.delete("asdf").get
val result = client.asyncGets("asdf").get
assert(result == null)
val response = client.asyncCAS("asdf", 1, "bar").get
response match {
case CASResponse.NOT_FOUND => println("Document Not Found")
case CASResponse.EXISTS => println("Document exists")
}
}
Adding Thread.sleep(1000) before the update call fixes the problem, so my question is this the expected behaviour of Couchbase?
Couchbase version is 2.2.0 enterprise edition (build-821), using the Java client version 1.2.1 in Scala 2.10.2.
Thanks

I think you probably want to do:
client.delete(key, PersistTo.MASTER).get();
You can change the enum PersistTo to other options such as ONE,TWO,THREE (i.e. Master plus additional numbers of nodes). I tested your example with only one node and the above worked for me.

Have you tried use client.gets() instead of client.asyncGets().get() and client.cas() instead of client.asyncCAS().get()? I think it can solve your problem.

Related

How can I see how many documents were written & handle errors correctly?

From the documentation I can see that I should be able to use WriteResult.ok, WriteResult.code and WriteResult.n in order to understand errors and the number of updated documents but this isn't working. Here is a sample of what I'm doing (using reactiveMongoDB/Play JSON Collection Plugin):
def updateOne(collName: String, id: BSONObjectID, q: Option[String] = None) = Action.async(parse.json) { implicit request: Request[JsValue] =>
val doc = request.body.as[JsObject]
val idQueryJso = Json.obj("_id" -> id)
val query = q match {
case Some(_) => idQueryJso.deepMerge(Json.parse(q.get).as[JsObject])
case None => idQueryJso
}
mongoRepo.update(collName)(query, doc, manyBool = false).map(result => writeResultStatus(result))
}
def writeResultStatus(writeResult: WriteResult): Result = {
// NOT WORKING
if(writeResult.ok) {
if(writeResult.n > 0) Accepted else NotModified
} else BadRequest
}
Can I give an alternative approach here? You said:
"in order to understand errors and the number of updated documents but this isn't working"
Why you don't use the logging functionality that Play provides? The general idea is that:
You set the logging level (e.g., only warning and errors, or errors, etc.).
You could use the log to output a message in any case, either something is ok, or it is not.
Play saves the logs of your application while it is running.
You the maintainer/developer could look into the logs to check if there is any errors.
This approach open a great possibility in the future: you could save the logs into a third-party service and put monitoring functionalities on the top of it.
Now if we look at the documentation here, you see about different log levels, and how to use the logger.

Pure not a member of objective Promise in PlayFramework

I am learning how to work with both Scala and the PlayFramework for a project I am doing. Since my objective is similar to the one presented in this blog I am basing my code in it. However while trying to replicate that code I am finding an error in this
def stats( id: String ) = WebSocket.async[JsValue] { request =>
Hosts.hosts.find( _.id == id ) match {
case Some( host ) => Statistics.attach( host )
case None => {
val enumerator = Enumerator
.generateM[JsValue]( Promise.timeout( None, 1.second ) )
.andThen( Enumerator.eof )
Promise.pure( ( Iteratee.ignore[JsValue], enumerator ) )
}
}
}
The errors says value Pure is not a member of object play.api.libs.concurrent.Promise, initally I thought since this code was based on an older version of Play, something had changed. However I went to check the changelog and Promise seemed mostly unchanged, and according to the documentation Pure is still a member of it. It's probably something really simple but being new to this I am relatively confused on why this error is happening since the code should be tried and tested and still compatible with this version.
That's using a much older version of the Play libraries. Promise.pure was deprecated in 2.2.x, and removed in 2.3.x. You can use scala.concurrent.Future.successful instead.
Future.successful( ( Iteratee.ignore[JsValue], enumerator ) )

Using Streams in Gatling repeat blocks

I've come across the following code in a Gatling scenario (modified for brevity/privacy):
val scn = scenario("X")
.repeat(numberOfLoops, "loopName") {
exec((session : Session) => {
val loopCounter = session.getTypedAttribute[Int]("loopName")
session.setAttribute("xmlInput", createXml(loopCounter))
})
.exec(
http("X")
.post("/rest/url")
.headers(headers)
.body("${xmlInput}"))
)
}
It's naming the loop in the repeat block, getting that out of the session and using it to create a unique input XML. It then sticks that XML back into the session and extracts it again when posting it.
I would like to do away with the need to name the loop iterator and accessing the session.
Ideally I'd like to use a Stream to generate the XML.
But Gatling controls the looping and I can't recurse. Do I need to compromise, or can I use Gatling in a functional way (without vars or accessing the session)?
As I see it, neither numberOfLoops nor createXml seem to depend on anything user related that would have been stored in the session, so the loop could be resolved at build time, not at runtime.
import com.excilys.ebi.gatling.core.structure.ChainBuilder
def addXmlPost(chain: ChainBuilder, i: Int) =
chain.exec(
http("X")
.post("/rest/url")
.headers(headers)
.body(createXml(i))
)
def addXmlPostLoop(chain: ChainBuilder): ChainBuilder =
(0 until numberOfLoops).foldLeft(chain)(addXmlPost)
Cheers,
Stéphane
PS: The preferred way to ask something about Gatling is our Google Group: https://groups.google.com/forum/#!forum/gatling

Error inserting document into mongodb from scala

Trying to insert into a mongodb database from scala. the below codes dont create a db or collection. tried using the default test db too. how do i perform CRUD operations?
object Store {
def main(args: Array[String]) = {
def addMongo(): Unit = {
var mongo = new Mongo()
var db = mongo.getDB("mybd")
var coll = db.getCollection("somecollection")
var obj = new BasicDBObject()
obj.put("name", "Mongo")
obj.put("type", "db")
coll.insert(obj)
coll.save(obj)
println("Saved") //to print to console
}
}
On a first glance things look OK in your code although you have that stray def addMongo(): Unit = {
code at the top. I'll defer to a suggestion on looking for errors here.... Two items of note:
1) save() and insert() are complementary operations - you only need one. insert() will always attempt to create a new document ... save() will create one if the _id field isn't set, and update the represented _id if it does.
2) Mongo clients do not wait for an answer to a write operation by default. It is very possible & likely that an error is occurring within MongoDB causing your write to fail. the getLastError() command will return the result of the last write operation on the current connection. Because MongoDB's Java driver uses connection pools you have to tell it to lock you onto a single connection for the duration of an operation you want to run 'safely' (e.g. check result). This is the easiest way from the Java driver (in Scala, sample code wise, though):
mongo.requestStart() // lock the connection in
coll.insert(obj) // attempt the insert
getLastError.throwOnError() // This tells the getLastError command to throw an exception in case of an error
mongo.requestDone() // release the connection lock
Take a look at this excellent writeup on MongoDB's Write Durability, which focuses specifically on the Java Driver.
You may also want to take a look at the Scala driver I maintain (Casbah) which wraps the Java driver and provides more scala functionality.
We provide among other things an execute-around-method version of the safe write concept in safely() which makes things a lot easier for testing for writes' success.
You just missed the addMongo call in main. The fix is trivial:
object Store {
def main(args: Array[String]) = {
def addMongo(): Unit = {
var mongo = new Mongo()
var db = mongo.getDB("mybd")
var coll = db.getCollection("somecollection")
var obj = new BasicDBObject()
obj.put("name", "Mongo")
obj.put("type", "db")
coll.insert(obj)
coll.save(obj)
println("Saved") //to print to console
}
addMongo // call it!
}

How to cache results in scala?

This page has a description of Map's getOrElseUpdate usage method:
object WithCache{
val cacheFun1 = collection.mutable.Map[Int, Int]()
def fun1(i:Int) = i*i
def catchedFun1(i:Int) = cacheFun1.getOrElseUpdate(i, fun1(i))
}
So you can use catchedFun1 which will check if cacheFun1 contains key and return value associated with it. Otherwise, it will invoke fun1, then cache fun1's result in cacheFun1, then return fun1's result.
I can see one potential danger - cacheFun1 can became to large. So cacheFun1 must be cleaned somehow by garbage collector?
P.S. What about scala.collection.mutable.WeakHashMap and java.lang.ref.* ?
See the Memo pattern and the Scalaz implementation of said paper.
Also check out a STM implementation such as Akka.
Not that this is only local caching so you might want to lookinto a distributed cache or STM such as CCSTM, Terracotta or Hazelcast
Take a look at spray caching (super simple to use)
http://spray.io/documentation/1.1-SNAPSHOT/spray-caching/
makes the job easy and has some nice features
for example :
import spray.caching.{LruCache, Cache}
//this is using Play for a controller example getting something from a user and caching it
object CacheExampleWithPlay extends Controller{
//this will actually create a ExpiringLruCache and hold data for 48 hours
val myCache: Cache[String] = LruCache(timeToLive = new FiniteDuration(48, HOURS))
def putSomeThingInTheCache(#PathParam("getSomeThing") someThing: String) = Action {
//put received data from the user in the cache
myCache(someThing, () => future(someThing))
Ok(someThing)
}
def checkIfSomeThingInTheCache(#PathParam("checkSomeThing") someThing: String) = Action {
if (myCache.get(someThing).isDefined)
Ok(s"just $someThing found this in the cache")
else
NotFound(s"$someThing NOT found this in the cache")
}
}
On the scala mailing list they sometimes point to the MapMaker in the Google collections library. You might want to have a look at that.
For simple caching needs, I'm still using Guava cache solution in Scala as well.
Lightweight and battle tested.
If it fit's your requirements and constraints generally outlined below, it could be a great option:
Willing to spend some memory to improve speed.
Expecting that keys will sometimes get queried more than once.
Your cache will not need to store more data than what would fit in RAM. (Guava caches are local to a single run of your application.
They do not store data in files, or on outside servers.)
Example for using it will be something like this:
lazy val cachedData = CacheBuilder.newBuilder()
.expireAfterWrite(60, TimeUnit.MINUTES)
.maximumSize(10)
.build(
new CacheLoader[Key, Data] {
def load(key: Key): Data = {
veryExpansiveDataCreation(key)
}
}
)
To read from it, you can use something like:
def cachedData(ketToData: Key): Data = {
try {
return cachedData.get(ketToData)
} catch {
case ee: Exception => throw new YourSpecialException(ee.getMessage);
}
}
Since it hasn't been mentioned before let me put on the table the light Spray-Caching that can be used independently from Spray and provides expected size, time-to-live, time-to-idle eviction strategies.
We are using Scaffeine (Scala + Caffeine), and you can read abouts its pros/cons compared to other frameworks over here.
You add your sbt,
"com.github.blemale" %% "scaffeine" % "4.0.1"
Build your cache
import com.github.blemale.scaffeine.{Cache, Scaffeine}
import scala.concurrent.duration._
val cachedItems: Cache[String, Int] =
Scaffeine()
.recordStats()
.expireAtferWrite(60.seconds)
.maximumSize(500)
.build[String, Int]()
cachedItems.put("key", 1) // Add items
cache.getIfPresent("key") // Returns an option