1

I'm writing a Play/Scala application using Play 2.5.4 and ReactiveMongo. Based on this example, I'm getting the collection using

class SettingStore( val mongo:ReactiveMongoApi) {
  def collection = mongo.db.collection[BSONCollection]("Settings")
  // more code...
}

However, db is now deprecated. The deprecation warning recommends I use database, but this one returns a Future so all operations have to be mapped over. Since ReactiveMongo's operations also return Futures, this seems redundant... what's to proper way of getting a collection? (or, am I missing something completely and Future[Future[Future[A]]] is the future?)

cchantep
  • 9,118
  • 3
  • 30
  • 41
Michael Bar-Sinai
  • 2,729
  • 20
  • 27
  • You must use `.flatMap()` or `for comprehension` – andrey.ladniy Jun 14 '16 at 05:35
  • Thanks. But `def coll2 = for ( db <- mongo.database ) yield db.collection[BSONCollection]("GeoMaps")` still yields a `Future[BSONCollection]`... am I doing this wrong? – Michael Bar-Sinai Jun 14 '16 at 19:56
  • Yes. You are rught. But i don't understant problem. `Future[BSONCollection]` you can `.map()` to another `Future[T]`. In `Action` you can use `.async()` with result of `Future[Result]`. In showed example all results are `Future[T]`/ – andrey.ladniy Jun 15 '16 at 05:56
  • That's true, but is kind of silly (I think). The database is obtained once, right after the object is instantiated. But this way, I'm paying the extra `Future.map` on each access to the collection (NOT the db). My logic says, if I obtain it once, I need to pay the `Future` once. – Michael Bar-Sinai Jun 15 '16 at 09:34
  • What about pool for db? Why collection must be instantinated once (you can do parallel requests to one collection)? – andrey.ladniy Jun 15 '16 at 10:04
  • The scaladoc for `MongoConnection` notes that "many connections (channels) are open on all the available servers in the replica set". I wonder why there's no good example for anything that's not using the controller directly (i.e. mixin with `MongoController`). Oddly, `MongoController` does provide a non-future database in the field `db`. The thing is, using it mixes the control and storage layers, which is not so clean... the whole point of using Play! was that it makes it easy to create and maintain clean design. Weird. – Michael Bar-Sinai Jun 15 '16 at 21:48
  • All wath you need for requests with ReactiveMongo is `ReactiveMongoApi`. This trait must be used by DI. `MongoController` is only wrapper for `val reactiveMongoApi: ReactiveMongoApi`. So you can create independent `class Service @Inject()(val reactiveMongoApi: ReactiveMongoApi)(implicit exec: ExecutionContext) {...}` – andrey.ladniy Jun 16 '16 at 05:22
  • `ReactiveMongoApi` has depricated `db` and `database`. Why `db` depricated? I think, this make so because `database` is implemented with waiting for available connection and that is why this is Future[DefaultDB]. – andrey.ladniy Jun 16 '16 at 05:37

1 Answers1

1

If you have a look at the documentation, you can see examples using the .database function, instead of the deprecated .db.

The non-async .db has been deprecated as it didn't offer sufficient guaranty to be able to find an active connection in the MongoConnection pool.

It was assuming at least one connection is active as soon as the pool is started, which is not always the case as checking/discovering the ReplicaSet nodes can take time, according the network speed/latency.

The same assertion can be wrong in case the driver cannot join the nodes for some time (network interruption, nodes restarted, ...). It can take some time so the nodes indicate they are back on line.

The new .database resolution is async, and use a FailoverStrategy to wait (or not) for an available connection (according the chosen read preference, ...).

cchantep
  • 9,118
  • 3
  • 30
  • 41