-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP : begin working on gridfs implementation #29
base: master
Are you sure you want to change the base?
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idem
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ne correspond pas à une version existante : https://search.maven.org/ ou http://reactivemongo.org/
@@ -124,6 +124,7 @@ lazy val gridfs = project.in(file("gridfs")). | |||
settings(Common.settings: _*).settings( | |||
name := "benji-gridfs", | |||
libraryDependencies ++= Seq( | |||
Dependencies.slf4jApi, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- prefix en paramètre
- le transport et même derrière storage et
BucketRef
etObjectRef
doivent resource la DB au moment des appels/opérations (à partir du nom de DB dans l'URI)
package com.zengularity.benji.gridfs | ||
|
||
import reactivemongo.api.MongoConnection | ||
|
||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Option.get
est un code smell/bas practice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pourquoi ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copy paste ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, je ne me suis pas encore penché là dessus
@@ -7,7 +7,7 @@ import reactivemongo.api.MongoConnection | |||
|
|||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 com.zengularity.benji.exception.BenjiUnknownError | ||
import scala.util.Success |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double import
|
||
import reactivemongo.api.gridfs.GridFS | ||
import reactivemongo.api.BSONSerializationPack | ||
import scala.concurrent.{ ExecutionContext, Future } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oubli ?
} 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 @@ | |||
// /* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formulation message "Fails to ..."
|
||
import reactivemongo.api.MongoConnection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
recoverWith
vs recover
|
||
filesAndChunksStats.transform { | ||
case Success(_) => Success(true) | ||
case Failure(_) => Success(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?