Open elijahbenizzy opened 4 months ago
This is very likely dependent on #33 -- we'll need to layer/apply updates to state in a nice way. We can probably get around that but it is worth considering.
What I would do today is just do it internal to the action:
@action(...)
def my_parallel_action(state: State, .. ) -> tuple(dict, state):
# do the parallelization myself with threading/asyncio/etc.
futures = [ ... ]
# wait for first, or wait for all
result = wait_for_futures(futures)
# do state update here / handle any failures etc
state = update_state(state, result)
return result, state
So the question if we provide framework support for something like this is "what are we removing/simplifying/enhancing'"?
What I would do today is just do it internal to the action:
@action(...) def my_parallel_action(state: State, .. ) -> tuple(dict, state): # do the parallelization myself with threading/asyncio/etc. futures = [ ... ] # wait for first, or wait for all result = wait_for_futures(futures) # do state update here / handle any failures etc state = update_state(state, result) return result, state
So the question if we provide framework support for something like this is "what are we removing/simplifying/enhancing'"?
Not a requirement (yet). But the enhancement is visibility/telemetry/checkpointing for long-running jobs.
Furthermore, when we combine this with the ability to build actions recursively then it really simplifies things.
Say you're building a PR bot such as ellipsis. You'll want to respond to each comment in parallel, otherwise it'll take too long. Each comment could be a multi-step process. This + composable actions make that feasible. Again, not necessary (there are multiple ways to model it).
Plan of action:
Use-case (sample, for scrapegraph):
One subgraph points to the other. This is a spawner/subgraph relationship (not to be confused with parent
Design for phase (1):
@action(...)
def spawning_action(..., __context: AppContext):
app = (
ApplicationBuilder()...
.with_spawning_parent(
__context.app_id,
__context.sequence_id)
.with_tracker(__context.tracker)
.build()
)
... = app.run(...)
return ...
Overview
We should be able to launch a whole bunch of actions in parallel. Walking the state machine in parallel is tricky, so this proposes the following:
MultiAction
that performs a map operation over some state fieldmultithreading
(for sync) andasyncio
(for async)Use-cases
Requirements:
Design Qs: