-
Notifications
You must be signed in to change notification settings - Fork 0
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
Introduce MonadError & refactor Doobie classes #113
Conversation
JaCoCo code coverage report - scala 2.12.17
Files
|
JaCoCo code coverage report - scala 2.13.12
Files
|
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.
Just quickly went through the code. Overall the idea LGTM, especially the Doobie part. However, I didn't do a deep review of the internal implementation (I can't now).
@@ -47,29 +49,33 @@ abstract class DBFunction[I, R, E <: DBEngine[F], F[_]](functionNameOverride: Op | |||
* @param values - The values to pass over to the database function. | |||
* @return - A sequence of results from the database function. | |||
*/ | |||
protected def multipleResults(values: I): F[Seq[R]] = dBEngine.fetchAll(query(values)) | |||
protected def multipleResults(values: I)(implicit ME: MonadError[F, Throwable]): F[Seq[R]] = |
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.
Why ME
not me
? I saw some other place with implicit lowercase, so probably makes sense to be me
instead.
(same in other methods)
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.
ok, will change everywhere to lower case
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.
done
import org.scalatest.funsuite.AnyFunSuite | ||
import za.co.absa.fadb.DBSchema | ||
import za.co.absa.fadb.doobie.DoobieFunction.DoobieMultipleResultFunction | ||
|
||
class DoobieMultipleResultFunctionTest extends AnyFunSuite with DoobieTest { | ||
|
||
class GetActors(implicit schema: DBSchema, dbEngine: DoobieEngine[IO]) | ||
extends DoobieMultipleResultFunction[GetActorsQueryParameters, Actor, IO] { | ||
// implicit def toFragmentsFunctionSemigroup[T]: Semigroup[T => Seq[Fragment]] = { |
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.
What is this 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.
Just a left over code, will remove it.
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.
done
@lsulak @jakipatryk |
Test run GH jacoco post |
added the missing comma |
|
@salamonpavel Create please |
@miroslavpojer |
Created Issue - #116 to finish found problem with manual Integration test run - short doc & missing test data expected by tests. |
@@ -16,6 +16,7 @@ | |||
|
|||
package za.co.absa.fadb.doobie | |||
|
|||
import cats.Monad |
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 this actually used?
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.
good catch
functionNameOverride: Option[String] = None | ||
)(implicit override val schema: DBSchema, | ||
)(implicit | ||
override val schema: DBSchema, | ||
val dbEngine: DoobieEngine[F], | ||
val readR: Read[R], | ||
val readSelectWithStatus: Read[StatusWithData[R]] |
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 like the formatting of these.
Btw, some code docs have very long lines, can you improve that?
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.
Ok, shortened the docs.
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 finished with the review, very interesting - the idea behind all these fragments and the way it's used
Co-authored-by: Ladislav Sulak <[email protected]>
Co-authored-by: Ladislav Sulak <[email protected]>
In the provided code,
MonadError
is used to catch exceptions that might be thrown when constructing the SQL query. If an exception is thrown, it is caught and represented as a failure in theF
context.MonadError
is a type class in Scala that abstracts over data types which define aflatMap
operation and can signal errors. This includes types likeOption
,Either
,Try
,Future
,IO
, etc.Apart from introduction of MonadError into both Slick and Doobie module, the Doobie functions have undergone a further significant refactoring process. Users have to provide function value from input to sequence of Doobie
Fragment
s during the construction phase, thereby ensuring that no code can escape from the computational contextF
. This not only enhances the safety and predictability of the code but also eliminates a substantial amount of boilerplate. The ability to concatenate DoobieFragment
s has facilitated this transformation, enabling flexible and dynamic construction of SQL queries.However, this refactoring strategy could not be directly applied to the Slick module due to the lack of support for concatenation in
SQLActionBuilder
. This limitation necessitates the implementation of thesql
method within the class body when using Slick.An example of code throwing exception that's not captured in the computational context. Notice that the
Fragment
is constructed outside of computationalIO
context.An example where the error is captured within its context. Notice the simplification and reduction of boilerplate code and the fact that function from input type to
Seq[Fragment]
is needed to be passed to the constructor.The function passed to the constructor is of this signature.
The
sql
method is already implemented in terms ofmeSql
and made final.toFragmentsSeq
is evaluated within the MonadError context. Exceptions can't escape.In Slick module the similar is accomplished in this way. User still needs to implement
sql
method in the classes body.meSql
then wraps this code in the computational context. Since thesql
method is passed by-name, potential exceptions won't escape. From user point of view the Slick api hasn't changed.Now back to Doobie module....
Given that the arguments to the sql function are passed as a function this opens door for functional composition and reusability.
Fixes #114