<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Jul 8, 2014 at 11:31 PM, Joshua Harlow <span dir="ltr"><<a href="mailto:harlowja@yahoo-inc.com" target="_blank">harlowja@yahoo-inc.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">I think clints response was likely better than what I can write here, but<br>


I'll add-on a few things,<br>
<div class=""><br>
<br>
>How do you write such code using taskflow?<br>
><br>
>  @asyncio.coroutine<br>
>  def foo(self):<br>
>      result = yield from some_async_op(...)<br>
>      return do_stuff(result)<br>
<br>
</div>The idea (at a very high level) is that users don't write this;<br>
<br>
What users do write is a workflow, maybe the following (pseudocode):<br>
<br>
# Define the pieces of your workflow.<br>
<br>
TaskA():<br>
  def execute():<br>
      # Do whatever some_async_op did here.<br>
<br>
  def revert():<br>
      # If execute had any side-effects undo them here.<br>
<br>
TaskFoo():<br>
   ...<br>
<br>
# Compose them together<br>
<br>
flow = linear_flow.Flow("my-stuff").add(TaskA("my-task-a"),<br>
TaskFoo("my-foo"))<br></blockquote><div><br></div><div>I wouldn't consider this composition very user-friendly.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


# Submit the workflow to an engine, let the engine do the work to execute<br>
it (and transfer any state between tasks as needed).<br>
<br>
The idea here is that when things like this are declaratively specified<br>
the only thing that matters is that the engine respects that declaration;<br>
not whether it uses asyncio, eventlet, pigeons, threads, remote<br>
workers[1]. It also adds some things that are not (imho) possible with<br>
co-routines (in part since they are at such a low level) like stopping the<br>
engine after 'my-task-a' runs and shutting off the software, upgrading it,<br>
restarting it and then picking back up at 'my-foo'.<br></blockquote><div><br></div><div>It's absolutely possible with coroutines and might provide even clearer view of what's going on. Like this:<br><br><font face="courier new, monospace">@asyncio.coroutine</font></div>

<div><font face="courier new, monospace">def my_workflow(ctx, ...):</font></div><div><font face="courier new, monospace">    project = yield from ctx.run_task(create_project())</font></div><div><font face="courier new, monospace">    # Hey, we don't want to be linear. How about parallel tasks?</font></div>

<div><font face="courier new, monospace">    volume, network = yield from asyncio.gather(</font></div><div><font face="courier new, monospace">        ctx.run_task(create_volume(project)),</font></div><div><font face="courier new, monospace">        ctx.run_task(create_network(project)),</font></div>

<div><font face="courier new, monospace">    )</font></div><div><font face="courier new, monospace">    # We can put anything here - why not branch a bit?</font></div><div><font face="courier new, monospace">    if create_one_vm:</font></div>

<div><font face="courier new, monospace">        yield from ctx.run_task(create_vm(project, network))</font></div><div><font face="courier new, monospace">    else:</font></div><div><font face="courier new, monospace">        # Or even loops - why not?</font></div>

<div><font face="courier new, monospace">        for i in range(network.num_ips()):</font></div><div><font face="courier new, monospace">            yield from ctx.run_task(create_vm(project, network))</font></div><div><br>

</div><div>There's no limit to coroutine usage. The only problem is the library that would bind everything together.</div><div>In my example run_task will have to be really smart, keeping track of all started tasks, results of all finished ones, skipping all tasks that have already been done (and substituting already generated results).</div>

<div>But all of this is doable. And I find this way of declaring workflows way more understandable than whatever would it look like with Flow.add's</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


Hope that helps make it a little more understandable :)<br>
<br>
-Josh<br></blockquote><div><br></div><div>PS: I've just found all your emails in this thread in Spam folder. So it's probable not everybody read them. </div></div><div><br></div>-- <br><br><div>Kind regards, Yuriy.</div>


</div></div>