-
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
Pass state to the data sources in a type-safe way #44
Comments
as I discovered today, a moderately satisfying solution to this is to fetch a new datasource, using the resource as an id. As an example: val config : Config = ???
def getHttpClient(c:Config): Fetch[HttpClient] = Fetch(c)
def getDataSource(httpClient: HttpClient) : Fetch[DataSource[Id, Data]] = Fetch(httpClient)
def getData(id: Id): Fetch[Data] =
for {
h <- getHttpClient(config)
ds <- getDataSource(h)
d <- Fetch(id)(ds)
} yield d It's unfortunate that the new datasource has to be passed in manually, but there's currently no way to mark variables in a for comprehension as implicit |
Would something like this fit the use case? Implicits is a natural way to inject dependencies in implementations. class HttpDataSource[I, R](implicit H: HttpClient) extends DataSource[I, R] {
def fetch(ids: NonEmptyList[I]): Eval[Map[I, R]] = H.get(...)
}
implicit def dataSource[I, R](implicit H: HttpClient): DataSource[I, R] =
new HttpDataSource[I, R]
Fetch(id) // datasource received implicitly Other than that @AlecZorab example is very reasonable. |
Sadly, if you generate a new data source for each fetch then multiple queries from the "same" source won't be aggregated. That's why I ended up fetching the source instead |
Actually, I say that, but I didn't investigate whether a proper equality definition would fix it. |
can confirm that if you have a proper equality definition for the datasource then you can do def getToken(): Fetch[Token] = ???
implicit def fixingSource(implicit t:Token): DataSource[Id, Data] = ???
def getData(id:Id) : Fetch[Data] = ???
getToken().flatMap(implicit t => getData(id)) Which will, perhaps, get a bit unwieldy in larger blocks, but is bearable for smaller |
It would be great to have not only the ability to pass config/etc. in, but also to be able to output values such as logs and metrics in a functional way (i.e. effectively ReaderWriterState). |
@gregbeech you can do that today with the Freestyle Fetch integration http://frees.io/docs/integrations/fetch/ using the |
@gregbeech Fetch currently already exposes some of that information through You get both the result and the environment by calling Would you like to see some additional logs/metrics? |
Currently,
DataSource#fetch
looks like this:The
fetch
method of a data source just receives a non empty list of identities. If we want to inyect some state to our data sources (for example an HTTP client to the data sources that make HTTP calls, a connection pool to the data sources that query a database, and so on) we must use the mechanisms that Scala gives us (implicits et al) since it's not directly supported by the library.It may make sense to support passing state in a type-safe way to the data sources and provide the concrete values when running a Fetch, much like Haxl does. Not sure about how it'd look like yet, but when running a fetch we'd have to provide an additional value with the inyected state. Can the type system make sure that we are providing the state for every data source used inside a fetch? Should this be supported by the libary?
The text was updated successfully, but these errors were encountered: