Support asynchronous data sources - #54
Conversation
|
I looked at the whole set of changes. Excellent work!
I think we need to:
I think loosing the abstraction over the target monad it's not acceptable as that is one of the main features for me to use I think What I'm trying to say is that there is no need to sacrifice abstracting over the return type while keeping the Task async and concurrent goodness. Thoughts? |
|
Based on your suggestions i reworked the pull request and dropped the coupling with The import cats.data.NonEmptyList
trait DataSource[Identity, Result]{
def fetchOne(id: Identity): Query[Option[Result]]
def fetchMany(ids: NonEmptyList[Identity]): Query[Map[Identity, Result]]
}The sealed trait Query[A] extends Product with Serializable
/** A query that can be satisfied synchronously. **/
final case class Sync[A](action: Eval[A]) extends Query[A]
type Callback[A] = A => Unit
type Errback = Throwable => Unit
/** A query that can only be satisfied asynchronously. **/
final case class Async[A](action: (Callback[A], Errback) => Unit, timeout: Duration)
extends Query[A]As you can see, the synchronous queries can be lifted to the target concurrency monad with a plain I still need to polish things here and there, i will write a task list in the PR description soon. |
|
This is awesome. I don't think we should use await in the docs. I think we should also provide examples for interpreting to Future, Task, Scalaz Task, etc... And synchronous ones with big warnings about their blocking and unsafe nature such as Id, Option, Eval, etc... In any case this is a great advancement in performance and design IMHO |
|
this PR looks great! 👍 |
| ``` | ||
|
|
||
| Now that we have created a fetch, we can run it to a target monad. Note that the target monad (`Eval` in our example) needs to implement `MonadError[M, Throwable]`, we provide an instance for `Eval` in `fetch.implicits._`, that's why we imported it. | ||
| Now that we have created a fetch, we can run it to a `Task`. Note that when we create a task we are not computing any value yet. Having a `Task` instance allows us to try to run it synchronously or asynchronously, choosing a scheduler. |
There was a problem hiding this comment.
I don't see any reference to Task in these code snippets. (Not being familiar with the codebase) I'm assuming that import fetch.implicits._ brings it in (or an implicit conversion from Fetch -> Task). It might be worth calling that out if so explicitly somewhere in the README.
|
Looks good from me, looking forward to playing with it. |
|
Just finished documenting all of this, if you can proofread it and comment will be appreciated! |
| ``` | ||
|
|
||
| Now that we have created a fetch, we can run it to a target monad. Note that the target monad (`Eval` in our example) needs to implement `MonadError[M, Throwable]`, we provide an instance for `Eval` in `fetch.implicits._`, that's why we imported it. | ||
| We'll run our fetches to the ambiend `Id` monad in our examples, let's do some imports. |
|
LGTM. Outstanding job! |
|
|
||
| ```scala | ||
| "com.fortysevendeg" %% "fetch" %% "0.2.0" | ||
| "com.fortysevendeg" %% "fetch" % "0.2.0" |
There was a problem hiding this comment.
I'm guessing that these versions will change once a new build is made from this PR.
There was a problem hiding this comment.
Yep, these changes will be released in a 0.3.0 version
|
I've left a whole bunch of comments on the README, mainly from a newbies "I don't understand" POV. Hope they're helpful :) |
|
@tomjadams really valuable feedback, thanks a lot! I'll go through them tomorrow and make sure they get addressed. |
|
I may have gone a bit nuts :) I just found a few things confusing from a beginners POV. — |
4fbf2f7 to
8088021
Compare
Current coverage is 60.84%@@ master #54 diff @@
==========================================
Files 7 9 +2
Lines 106 189 +83
Methods 105 149 +44
Messages 0 0
Branches 1 5 +4
==========================================
+ Hits 82 115 +33
- Misses 24 74 +50
Partials 0 0
|
18b31fa to
d80da1f
Compare
|
LGTM! |
|
Again, amazing job! |
|
|
Addresses #52. I also made an improvement: calling
fetchOneandfetchManydepending on the number of the identities to be fetched. @raulraja please take a look!Idas the target monad in the examplesQueryconstructorsQueryconstructors: only leavesync(receiving a thunk),asyncandeval(lifts eval to synchronous query)Edit: leaving more thorough testing as part of #32
- [ ] Test Monix integration more thoroughly