I am trying to use the Cats Mongo implementation (https://github.com/Kirill5k/mongo4cats) in ZIO 2.
There is a chapter in ZIO 2's doc (https://zio.dev/guides/interop/with-cats-effect#converting-resource-to-zmanaged-1) how one can convert a Cats resource to ZManaged.
But in ZIO 2 using scopes instead of ZManaged is the way to go.
How do I implement that conversion?
This is the cats resource:
def catsEmbeddedMongo[F[_]: cats.effect.Async]: Resource[F, MongoClient[F]] = MongoClient.fromConnectionString[F]("mongodb://localhost:27017")
You can call toScopedZIO with:
catsEmbeddedMongo[Task].toScopedZIO
In the context of mongo4cats library, you can also use mongo4cats-zio module, which provides integration with ZIO 2. Docs: https://kirill5k.github.io/mongo4cats/docs/zio.html
Related
I'm evaluating the MongoDB async driver:
https://github.com/mongodb/mongo-scala-driver
The API looks pretty simply, but how could I do the following transformation?
val collection: MongoCollection[Document] = database.getCollection("test")
I would like to do an implicit transformation when I do CRUD operations on the database. I could not find enough information in the reference documentation on how to do an implicit transformation.
Could anyone point me to any reference on how to do an implicit transformation?
The scala driver is only a thin wrapper around the java driver rather than a pure implementation :( ... so you have to follow the java driver's conventions and provide a codec. I don't have a working example, but you should be able to follow this: http://mongodb.github.io/mongo-java-driver/3.3/bson/codecs/ and register a codec for a scala class.
I'm trying to understand the idea and purpose behind scalaz concurrent package, primarily Future and Task classes, but when using them in some application, it's now far from simple sequential analog, whereas scala.concurrent.Future, works more then better. Can any one share with his experience on writing concurrent/asynchronous application with scalaz, basically how to use it's async method correctly? As i understand from the sources async doesn't use a separate thread like the call to standard future, or fork/apply methods from scalaz works, so why it is called async then? Does it mean that in order to get real concurrency with scalaz i always have to call fork(now(...)) or apply?
I'm not a scalaz expert, but I'll try to help you a little bit. Let me try answer your questions one by one:
1) Can any one share with his experience on writing concurrent/asynchronous application with scalaz, basically how to use it's async method correctly?
Let's first take a look at async signature:
def async[A](listen: (A => Unit) => Unit): Future[A]
This could be a bit cryptic at first, so as always it's good idea to look at tests to understands possible use cases. In https://github.com/scalaz/scalaz/blob/scalaz-seven/tests/src/test/scala/scalaz/concurrent/FutureTest.scala
you can find the following code:
"when constructed from Future.async" ! prop{(n: Int) =>
def callback(call: Int => Unit): Unit = call(n)
Future.async(callback).run must_==
}
As we know from signature Future.async just construct new Future using function of signature (A => Unit) => Unit. What this really means is that Future.async takes as parameter function which for given callback makes all required computations and pass the result to that callback.
What is important to note it that Future.async does not run any computations on itself, it only prepare structure to run them later.
2) As i understand from the sources async doesn't use a separate thread like the call to standard future, or fork/apply methods from scalaz works, so why it is called async then?
You are correct. Only fork and apply seems to be running anything using threads, which is easy to notice looking at the signatures which contains implicit pool: ExecutorService. I cannot speak for the authors here, but I guess async is related to the callback. It means that rather than blocking on Future to get it result at the end you will use asynchronous callback.
3) Does it mean that in order to get real concurrency with scalaz i always have to call fork(now(...)) or apply?
From what I can say, yes. Just notice that when you are creating Future using syntax Future(x) you are using apply method here, so this is kind of default behavior (which is fine).
If you want to better understand design of Scalaz Futures I can recommend you reading "Functional Programming in Scala". I believe this book is written by main Scalaz contributors and chapter 7 discusses designing API for purely functional parallelism library. It's not exactly the same as Scalaz Future, but you can see many similarities.
You can also read wonderful Timothy Perrett blog post about Scalaz Task and Future which covers many not so obvious details.
async is used to adapt an async, callback-based API as a Future. It's called async because it's expected that it will be used with something that runs asynchronously, perhaps calling the callback from another thread somewhere further down the line. This is "real" concurrency, provided the API you're calling really uses it asynchronously (e.g. I use Future.async with the async parts of the AWS SDK like AmazonSimpleDBAsyncClient).
If you want "real" concurrency from the scalaz Task API directly you need to use things like fork or gatherUnordered, as many of the APIs default towards being safe/deterministic and restartable, with concurrency only when explicitly requested.
When composing Tasks with map and flatMap you can get a performance win by not using fork, see:
http://blog.higher-order.com/blog/2015/06/18/easy-performance-wins-with-scalaz/
In groovy one can do:
class Foo {
Integer a,b
}
Map map = [a:1,b:2]
def foo = new Foo(map) // map expanded, object created
I understand that Scala is not in any sense of the word, Groovy, but am wondering if map expansion in this context is supported
Simplistically, I tried and failed with:
case class Foo(a:Int, b:Int)
val map = Map("a"-> 1, "b"-> 2)
Foo(map: _*) // no dice, always applied to first property
A related thread that shows possible solutions to the problem.
Now, from what I've been able to dig up, as of Scala 2.9.1 at least, reflection in regard to case classes is basically a no-op. The net effect then appears to be that one is forced into some form of manual object creation, which, given the power of Scala, is somewhat ironic.
I should mention that the use case involves the servlet request parameters map. Specifically, using Lift, Play, Spray, Scalatra, etc., I would like to take the sanitized params map (filtered via routing layer) and bind it to a target case class instance without needing to manually create the object, nor specify its types. This would require "reliable" reflection and implicits like "str2Date" to handle type conversion errors.
Perhaps in 2.10 with the new reflection library, implementing the above will be cake. Only 2 months into Scala, so just scratching the surface; I do not see any straightforward way to pull this off right now (for seasoned Scala developers, maybe doable)
Well, the good news is that Scala's Product interface, implemented by all case classes, actually doesn't make this very hard to do. I'm the author of a Scala serialization library called Salat that supplies some utilities for using pickled Scala signatures to get typed field information
https://github.com/novus/salat - check out some of the utilities in the salat-util package.
Actually, I think this is something that Salat should do - what a good idea.
Re: D.C. Sobral's point about the impossibility of verifying params at compile time - point taken, but in practice this should work at runtime just like deserializing anything else with no guarantees about structure, like JSON or a Mongo DBObject. Also, Salat has utilities to leverage default args where supplied.
This is not possible, because it is impossible to verify at compile time that all parameters were passed in that map.
I have this piece of code
for (element <- table.find;
Right(info) = exceptionManager(mapper.getInfoFromDbObject(element)))
yield info
and I would like to unit test it. I want to mock table.find in order to return a sequence of element that I want. I have tried mocking hasNext() and next() methods of Iterator interface but it seems it is not working. Which is the method to mock a for comprehension?
Each for comprehension is translated to map, flatMap, filter method calls. So you should mock at least them.
You can find more information here (for example):
http://www.lambdascale.com/2010/12/the-adventures-of-a-java-developer-in-monadland/
And of course you will find deep explanation in Programming in Scala book.
Edit
But as Dave Griffith said, you can just initialize new Iterator yourself. Here is an example that uses Mockito and ScalaTest:
val table = mock[TableClass]
when(table find) thenReturn Iterator(new ModelObject(1), new ModelObject(2))
Edit 1
As Daniel noticed, filter method is now deprecated in for comprehensions. Instead you should use withFilter. For more information you can look in this thread:
http://scala-programming-language.1934581.n4.nabble.com/Rethinking-filter-td2009215.html#a2009218
and this related SO question:
guide to move from filter to withFilter?
In theory, you should mock the "map" method, but you're probably better off simply having table.find return one of the predefined collection types.
I'm using Groovy for testing and Scala for actual code. Obviously I often use Scala's collection types - but when I generate test data in Groovy I often use the java.util.*-types.
I started writing static conversion methods based on the scalaj-collection library. But that's just not 'groovy'.
What's the best approach to convert one to the other?
Might implicit conversions work somehow?
UPDATE:
For example if I wouldn't manually convert the types I of course get:
groovy.lang.MissingMethodException:
No signature of method: static setup is applicable for argument types: (java.util.ArrayList)
Possible solutions: setup(scala.collection.immutable.List)
Did you try the "built-in" implicit conversions?
import scala.collection.JavaConversions._
Another approach is to change your Scala code to use Java collection types when declaring parameters and rely on implicit conversions in the method body to get the benefit of Scala collections operations.