-
Notifications
You must be signed in to change notification settings - Fork 49
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
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! 👍 |
import fetch.syntax._ | ||
|
||
val fetchOne: Fetch[String] = fetchString(1) | ||
``` | ||
|
||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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! |
import fetch.syntax._ | ||
|
||
val fetchOne: Fetch[String] = fetchString(1) | ||
``` | ||
|
||
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. |
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.
Ambient
LGTM. Outstanding job! |
```scala | ||
"com.fortysevendeg" %% "fetch" %% "0.2.0" | ||
"com.fortysevendeg" %% "fetch" % "0.2.0" |
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'm guessing that these versions will change once a new build is made from this PR.
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, 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
fetchOne
andfetchMany
depending on the number of the identities to be fetched. @raulraja please take a look!Id
as the target monad in the examplesQuery
constructorsQuery
constructors: only leavesync
(receiving a thunk),async
andeval
(lifts eval to synchronous query)Edit: leaving more thorough testing as part of #32
- [ ] Test Monix integration more thoroughly