WIP : begin working on gridfs implementation#29
WIP : begin working on gridfs implementation#29nicolasdejonghe wants to merge 17 commits intomasterfrom
Conversation
.gitignore
Outdated
| vfs/src/test/resources/gcs-test.json | ||
| vfs/src/test/resources/local.conf | ||
| s3/src/test/resources/local.conf | ||
| .metals |
There was a problem hiding this comment.
Ce genre de fichier dépendant de l'env de dev/préférences développeur ne doit pas se retrouver ici, mais dans le .git/info/exclude, le .gitignore doit rester commun/agnostique de ce genre de chose
build.sbt
Outdated
| }, | ||
| libraryDependencies ++= Seq( | ||
| "org.reactivemongo" %% "reactivemongo" % "0.1x", | ||
| "com.typesafe.play" %% "play-json" % playVer.value, |
There was a problem hiding this comment.
Est-ce qu'on a besoin de cette dépendance ?
build.sbt
Outdated
| "org.reactivemongo" %% "reactivemongo" % "0.1x", | ||
| "com.typesafe.play" %% "play-json" % playVer.value, | ||
| Dependencies.slf4jApi, | ||
| "commons-io" % "commons-io" % "2.4" % Test) |
build.sbt
Outdated
| "com.typesafe.play" %% "play-json" % playVer.value, | ||
| Dependencies.slf4jApi, | ||
| "commons-io" % "commons-io" % "2.4" % Test) | ||
| "org.reactivemongo" %% "reactivemongo" % "0.17" |
There was a problem hiding this comment.
Ne correspond pas à une version existante : https://search.maven.org/ ou http://reactivemongo.org/
| settings(Common.settings: _*).settings( | ||
| name := "benji-gridfs", | ||
| libraryDependencies ++= Seq( | ||
| Dependencies.slf4jApi, |
There was a problem hiding this comment.
je ne pense pas que c'est nécessaire
|
|
||
| final class GridFSTransport() { | ||
|
|
||
| def apply(uri: String, connectionOptions: MongoConnectionOptions) { |
There was a problem hiding this comment.
Type de retour ? Pour savoir comment créer il faut savoir ce qu'on veut créer et sur quoi ça dépend
| //c'est l'idée, pour l'instant je tatonne encore sur comment récupérer la db de la connexion pour la passer à GridFS(...) | ||
| MongoConnection.parseURI(uri).map { parsedUri => | ||
| val connection = driver.connection(parsedUri, options = connectionOptions) | ||
| GridFS[BSONSerializationPack.type](conn, "fs") |
There was a problem hiding this comment.
- prefix en paramètre
- le transport et même derrière storage et
BucketRefetObjectRefdoivent resource la DB au moment des appels/opérations (à partir du nom de DB dans l'URI)
| import reactivemongo.api.gridfs.GridFS | ||
| import reactivemongo.api.{ BSONSerializationPack, MongoConnectionOptions } | ||
| import reactivemongo.api.BSONSerializationPack | ||
| import scala.concurrent.ExecutionContext.Implicits.global |
There was a problem hiding this comment.
On n'utilise pas le contexte global, sauf pour des tests (et encore)
| val gridfsdb = for { | ||
| mongoUri <- Future.fromTry(MongoConnection.parseURI(uri)) | ||
| con = driver.connection(mongoUri) | ||
| dn <- Future(mongoUri.db.get) |
There was a problem hiding this comment.
Option.get est un code smell/bas practice
There was a problem hiding this comment.
de la même façon qu'il ne faut pas essayer de sortir d'une Future on ne peut pas ignore le contexte optionnelle d'une valeur, il faut travailler avec/dedans (le .get n'aurait jamais dû être exposé dans l'API).
| */ | ||
| final class GridFSFactory extends StorageFactory { | ||
| @SuppressWarnings(Array("org.wartremover.warts.TryPartial")) | ||
| def apply(injector: Injector, uri: URI): ObjectStorage = { |
There was a problem hiding this comment.
yep, je ne me suis pas encore penché là dessus
| import reactivemongo.api.gridfs.GridFS | ||
| import reactivemongo.api.BSONSerializationPack | ||
| import scala.concurrent.ExecutionContext.Implicits.global | ||
| import scala.concurrent._ |
There was a problem hiding this comment.
On évite les import en wildcard, qui peuvent cacher des imports dans la scope implicit, par ailleurs il y a une ligne en dessous pour ce package
| case Some(name) => | ||
| con.database(name).map(db => | ||
| GridFS[BSONSerializationPack.type](db, prefix)) | ||
| case None => Future.failed(new RuntimeException(s"Couldn't get the db from $mongoUri")) |
There was a problem hiding this comment.
Si possible utiliser les types d'Exception Benji qui sont dans core
| def apply(uri: String, prefix: String)(implicit ec: ExecutionContext): GridFSTransport = { | ||
| val driver = new reactivemongo.api.MongoDriver | ||
|
|
||
| val gridfsdb = for { |
There was a problem hiding this comment.
Il ne faut pas assigner une Future issue de .database(..) (résolution de la DB depuis poil):
It’s generally a good practice not to assign the database and collection references to val (even to lazy val), as it’s better to get a fresh reference each time, to automatically recover from any previous issues (e.g. network failure).
http://reactivemongo.org/releases/0.1x/documentation/tutorial/connect-database.html
| import scala.util.{ Failure, Success, Try } | ||
|
|
||
| import com.zengularity.benji.exception.BenjiUnknownError | ||
| import scala.util.Success |
|
|
||
| import reactivemongo.api.gridfs.GridFS | ||
| import reactivemongo.api.BSONSerializationPack | ||
| import scala.concurrent.{ ExecutionContext, Future } |
There was a problem hiding this comment.
Sur la forme, J'essaie de me tenir à un ordre pour les imports, en groupant d'abord les importe JVM/Java classique, après les imports scalalib (import scala...), les imports libs externes (ici reactivemongo), les imports internes/cross pkg (com.zengularity.benji...).
Adaptation des règles javastyle, c'est configurable dans Intellij (Order import)
| def gridfs(prefix: String)(implicit ec: ExecutionContext): Future[GridFS[BSONSerializationPack.type]] = { | ||
| mongoUri.db match { | ||
| case Some(name) => | ||
| for { |
There was a problem hiding this comment.
for est utile avec plus d'un <- (map), sinon un .map (plus explicite et concis dans ce cas)
| case Some(name) => | ||
| for { | ||
| db <- connection.database(name) | ||
| gridfs = GridFS[BSONSerializationPack.type](db, prefix) |
There was a problem hiding this comment.
Quelle différence entre avoir cette ligne et avoir yield GridFS[BSONSerializationPack.type](db, prefix) ?
| } yield gridfs | ||
|
|
||
| case None => | ||
| Future.failed(new BenjiUnknownError(s"Couldn't get the db from $mongoUri")) |
There was a problem hiding this comment.
La formulation actuelle des erreurs est plutôt "Fails to ..."
| mongoUri <- MongoConnection.parseURI(uri) | ||
| con = driver.connection(mongoUri) | ||
| } yield (mongoUri, con) | ||
| val (mongoUri, connection) = (res.map(_._1), res.map(_._2)) |
There was a problem hiding this comment.
Pourquoi sortir du for à partir de là ?
| val (mongoUri, connection) = (res.map(_._1), res.map(_._2)) | ||
| connection match { | ||
| case Success(connection) => new Success(GridFSTransport(driver, connection, mongoUri)) | ||
| case Failure(_) => Failure[GridFSTransport](new BenjiUnknownError(s"Couldn't create the connection to $uri")) |
There was a problem hiding this comment.
Le détails de l'erreur/root cause est perdu (cf https://github.com/zengularity/benji/blob/master/core/src/main/scala/exception/BenjiException.scala#L17 )
| package com.zengularity.benji.gridfs | ||
|
|
||
| import com.zengularity.benji.{ Bucket, ObjectStorage } | ||
| import scala.concurrent.ExecutionContext.Implicits.global |
| } yield (mongoUri, con) | ||
| val (mongoUri, connection) = (res.map(_._1), res.map(_._2)) | ||
| connection match { | ||
| case Success(connection) => new Success(GridFSTransport(driver, connection, mongoUri)) |
There was a problem hiding this comment.
Success est une case class, pas de new (par ailleurs même pour les class on tend à fournir une factory/apply dans companion pour découpler l'init)
| @@ -0,0 +1,49 @@ | |||
| // /* | |||
| val (mongoUri, connection) = (res.map(_._1), res.map(_._2)) | ||
| connection match { | ||
| case Success(connection) => new Success(GridFSTransport(driver, connection, mongoUri)) | ||
| case Failure(_) => Failure[GridFSTransport](new BenjiUnknownError(s"Couldn't create the connection to $uri")) |
There was a problem hiding this comment.
Formulation message "Fails to ..."
| import scala.concurrent.{ ExecutionContext, Future } | ||
| import scala.util.{ Failure, Success, Try } | ||
|
|
||
| import reactivemongo.api.MongoConnection |
There was a problem hiding this comment.
Il y a un import reactivemongo.api.X plus bas => import reactivemongo.api.{ MongoConnection, X}
| } yield (con, mongoUri) | ||
|
|
||
| res match { | ||
| case Success((connection, mongoUri)) => Success(new GridFSTransport(driver, connection, mongoUri)) |
There was a problem hiding this comment.
Pourquoi sortir le case Success du yield précédent (ce qui au passage instancie/alloue un Tuple2 intermédiaire, même si ça n'est pas grave, est-ce utile ?)
| res match { | ||
| case Success((connection, mongoUri)) => Success(new GridFSTransport(driver, connection, mongoUri)) | ||
| case Failure(error) => Failure[GridFSTransport](new BenjiUnknownError(s"Fails to create the connection to $uri", Some(error))) | ||
| res.recoverWith { |
|
|
||
| filesAndChunksStats.transform { | ||
| case Success(_) => Success(true) | ||
| case Failure(_) => Success(false) |
There was a problem hiding this comment.
Une storage.transport.gridfs(name) ne devrait pas se retrouver ici
Pull Request Checklist
Fixes
Fixes #xxxx
Purpose
What does this PR do?
Background Context
Why did you take this approach?
References
Are there any relevant issues / PRs / mailing lists discussions?