-
Notifications
You must be signed in to change notification settings - Fork 4
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
Remote scheme provider #53
Conversation
Codecov Report
@@ Coverage Diff @@
## master #53 +/- ##
==========================================
- Coverage 88.77% 88.55% -0.23%
==========================================
Files 15 17 +2
Lines 303 428 +125
Branches 0 2 +2
==========================================
+ Hits 269 379 +110
- Misses 34 49 +15
Continue to review full report at Codecov.
|
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.
I can't really comment about the Cassandra part, I only looked at the code itself.
I left a few suggestions and there is one place that would be nice if it could be improved, but it seems difficult without making things more complex.
for { | ||
dataNative1 <- toDataTypeNative(tupleArgs._1) | ||
dataNative2 <- toDataTypeNative(tupleArgs._2) | ||
} yield DataType.Map(dataNative1, dataNative2) |
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.
Maybe :
for {
t1 <- typeArgs.headOption
t2 <- typeArgs.tail.headOption
} yield (toDataTypeNative(t1) |@| toDataTypeNative(t2)).map(DataType.Map)
_ <- clusterAPI.connect | ||
metadata <- clusterAPI.metadata | ||
_ <- clusterAPI.close | ||
} yield metadata |
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.
You could write this as
clusterAPI.connect >> clusterAPI.metadata << clusterAPI.close
orclusterAPI.connect *> clusterAPI.metadata <* clusterAPI.close
.
Where the first one is a bit closer to what you wrote (as it is defined in flatMap
syntax) while the second one (defined in cartesian
syntax) is probably used more often. In this case there is no real difference.
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.
Cool, I have a doubt here. I was trying to add a recover in the clusterAPI.metadata
call, because we want to call to clusterAPI.close
even when the previous call fails. What's the best way to achieve this from your point of view? Thanks
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.
There is this open PR in Cats : typelevel/cats#1662 (issue typelevel/cats#1630).
Doobie uses something similar in its Transactor
. ConnectionIO
can contain side effects though (and can thus define a MonadError
instance), and that is not something you can do with every Free
/ FreeS
.
You can use the guarantee
implementation from the PR linked to above after you interpret to an M
with a MonadError[M, Throwable]
It is possible we can do something like they do in quasar to create a MonadError
for FreeS
if your algebras contain the Error
effect, but that would need some more thought / work.
tables <- tableList.traverse(toCreateTable) | ||
indexes <- indexList.traverse(toCreateIndex(_)) | ||
userTypes <- userTypeList.traverse(toUserType) | ||
} yield keyspaces ++ tables ++ indexes ++ userTypes |
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.
You could also use |+|
here (Either
s Semigroup
uses the Semigroup
of the right side, and for Semigroup[List].combine
is :::
/ ++
).
keyspaceList.traverse(toCreateKeyspace) |+|
tableList.traverse(toCreateTable) |+|
indexList.traverse(toCreateIndex(_)) |+|
userTypeList.traverse(toUserType)
} yield metadata | ||
|
||
Either.catchNonFatal { | ||
Await.result(metadataF[ClusterAPI.Op].interpret[Future], 10.seconds) |
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.
I can see that schemaDefinition
needs to return an Either[...]
at the moment, I am not sure if we can change that somehow.
Currently it is unfortunate twice: first we immediately have to interpret a FreeS
and then we we have to block on a Future
. It doesn't appear to be trivial to change this though ...
If there is no way we can do that, I would put the Await
on the end.
val fut: Future[SchemaDefinitionProviderError, SchemaDefinition] =
metadataF[ClusterAPI.Op].interpret[Future].attempt.map {
_.leftMap (SchemaDefinitionProviderError(_)) flatMap { metadata =>
// ...
}
}
Await.result(fut, 10.seconds) // :(
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.
You're right, clearly the worst part of the PR :(
I created a ticket for changing the return type to M[_]
(#52)
def apply(e: Throwable): SchemaDefinitionProviderError = | ||
SchemaDefinitionProviderError(e.getMessage, Some(e)) | ||
} | ||
|
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.
Maybe you could add a type alias for Either[SchemaDefinitionProviderError, ?]
here?
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.
Definitely
userTypeList.traverse(toUserType) | ||
} | ||
} | ||
Await.result(fut, 10.seconds) |
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.
Is there a need to block if instead of all the methods in this class return a M[Whatever]
where M[_] : AsyncContext
and in this case is M[SchemaResult[SchemaDefinition]]
? all the calls such as extractIndexes(tableList)
etc.. would be part of a monadic chain instead of direct style.
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.
I created ticket #52
Should I solve this on this PR? I'm ok with that, I was trying to keep this PR shorter as possible
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.
In a new ticket is fine 👍
def toCreateKeyspace(keyspaceMetadata: KeyspaceMetadata): SchemaResult[CreateKeyspace] = | ||
Either.catchNonFatal { | ||
val name: String = Option(keyspaceMetadata.getName) | ||
.getOrElse(throw new NullPointerException("Schema name is null")) |
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.
Probably better to use an IllegalArgumentException
in this case
|
||
def toDataTypeNative(dataType: DatastaxDataType): SchemaResult[DataType.Native] = | ||
dataType.getName match { | ||
case Name.ASCII => DataType.Ascii.asRight |
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.
Where is asRight
defined? as
suually denotes an internal cast and if this is is just lifting the value into Either.Right
we should use toRight
or the right()
syntax from cats.
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.
asRight
is the new syntax in Cats (see PR typelevel/cats#1454).
asRight
and asLeft
where chosen so they can't be confused with the .right
and .left
methods on Either
for RightProjection
and LeftProjection
.
Fixes #51
This PR:
MetadataSchemaProvider.scala
implementing a SchemaProvider that fetches the information from aCluster
connection.SchemaConversions
trait for converting classes from Datastax to Troy