This stuff is freaking awesome. Thanks so much.
Daz

On Thu, Sep 19, 2013 at 5:31 PM, Marcin Erdmann
<marcin.erdm...@proxerd.pl>wrote:

> I think I managed to fulfill all the requirements in the implementation
> I've just pushed to my fork:
> https://github.com/erdi/gradle/tree/should-run-after.
>
> In the end I went for a simpler and what looks to be a more efficient
> solution. Basically when building the execution plan I track should run
> after edges that were visited and take snapshots of execution plan for any
> visited task that has should run after successors. When a cycle is detected
> (just like before, if we end up in a previously visited node that we
> haven't yet finished processing successors for) we check if we walked
> through any should run after edges. If yes then we remove that edge from
> the graph, restore execution plan to the state from before visiting the
> 'from node' of that edge and start processing successors of that task from
> scratch. If there are no should run after edges we travelled through and we
> detect a cycle then we report it.
>
> I'll add some docs for this over the weekend.
>
> Marcin
>
>
>
> On Sat, Sep 14, 2013 at 4:23 PM, Marcin Erdmann <marcin.erdm...@proxerd.pl
> > wrote:
>
>> Hi all,
>>
>> I started looking into how to implement shouldRunAfter task ordering
>> rule. Some time ago Adam wrote:
>>
>> The idea is to add a very weak task execution rule that only provides
>>> hints for execution order and implies nothing else. So, if A
>>> shouldRunAfterB then:
>>>
>>> 1. If A or B are not scheduled to run, ignore the rule.
>>> 2. Run A after B only if there are no other contradictory rules on the
>>> ordering of A and B. That is, ignore cycles introduced by shouldRunAfter
>>> rules.
>>> 3. The dependencies of A shouldRunAfter B and its dependencies.
>>> 4. If B fails or is not run, A can still be run.
>>> 5. If there is an idle worker thread and A is the only task whose
>>> dependencies have been satisfied, then run A regardless of whether B
>>> has beenrun or not. That is, prefer running the task over an idle
>>> worker thread.
>>>
>>> Similar to mustRunAfter, but different in #2 and #5 above.
>>>
>>
>> #1, #3 and #4 are straightforward. With regards to #2 the idea is to:
>>
>>    - at the beginning of
>>    DefaultTaskExecutionPlan.determineExecutionPlan() find all cycles in the
>>    execution graph using CachingDirectedGraphWalker the same way as in
>>    onOrderingCycle()
>>    - find the first cycle that has no shouldRunAfter edges and throw a
>>    CircularReferenceException
>>    - if no such cycles are found iterate over all cycles and for each
>>    remove the first found shouldRunAfter edge (possibly with some logging?) -
>>    this will break the cycle; it's possible that a cycle won't have a
>>    shouldRunAfter edge as some cycles may share a shouldRunAfter edge that 
>> has
>>    been already removed but because we checked for cycles without
>>    shouldRunAfter edges before we know that all cycles in this phase had such
>>    edge at one point
>>    - continue with execution plan determination
>>
>> The downside here is that we would be adding another graph traversal to
>> the process. On the other hand I don't see how we could detect and break
>> cycles with shouldRunAfter edges in them without doing so.
>>
>> With regards to #5, do I understand correctly that it simply means that
>> shouldRunAfter ordering should not be treated as a dependency in context of
>> TaskInfo.allDependenciesComplete()?
>>
>> Marcin
>>
>>
>
>

Reply via email to