Closed nordfjord closed 1 year ago
The Task vs Async naming feels a bit wonky on first look, even though it's following the logic of the naming in general. Other questions spring to mind:
ct
args be mandatory ? In general the reason I didn't just expose both on a single abstraction is that I wanted people to think before giving up the flowing of cancellation - in general given a Transact will involve an IO roundtrip, the perf overhead of Async vs Task is not going to be significant.list
and using non-struct
tuples still appropriate if going task
?inner as an
Inner/
Coreproperty and then letting people build extension methods? (I'm open to pushback that all you're doing is adding equivalent
TaskAPIs for any
Async` ones, but part of me feels we should validate that need in multiple systems before baking it). (In general I'd aim to keep DeciderCore minimal, i.e. no FSharp* signatures, but maybe some noise in there might be worthwhile if it keeps the F# layer easier to read through top to bottom?)I do appreciate the overall idea of removing technical noise from business logic of course, but perhaps having some helpers in a ubiquitous lower level shims lib might address that more generally e.g. https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/142
With the latest changes, I wonder whether doing a member val Core = inner
would not give you pretty much the same experience? or you could call it Task
or Internal
. Either way, providing that would give an escape hatch for concocting arbitrary variants by calling TransactExAsync
on that?
Are you using something like IcedTasks for CancellationToken -> Task<'T>
? If not, would skipping passing the CT match the real world usage in your app? Obviously one would not expose that in the real API, but having customised helpers live as type augmentations in a local helper lib might be a route to customising that (and hiding threading of cancellation)
We're moving towards using Tasks more and more and this API would be helpful in situations such as calling deciders from propulsion as propulsion handlers are now Task based while deciders are still Async.
The next RC of Propulsion will provide a lower level API based on Tasks, Funcs and struct tuples
However the default API (without Async
suffices in Factory
) will continue to use Async, obj tuples, and FSharpFuncs
Having _ct and/or Async.AwaitTask
in prod code can wait until a profiler tells you which ones need it
For this release, I'm going to expose a val Core : DeciderCore
so you can further prototype to cater for such needs by having type augmentations on Decider
in a global namespace within an app.
As discussed out of band, the key issue with the APIs in DeciderCore from a F# perspective is that they operate on Event seq
rather than Event list
(that and the struct tuples)
I'm hopeful that taking a bit longer before baking something noisy in will ultimately yield a better overall result, even if it's not entirely clear to either of us what that might actually become.
We're moving towards using Tasks more and more and this API would be helpful in situations such as calling deciders from propulsion as propulsion handlers are now Task based while deciders are still Async.