Page MenuHomePhabricator

Issue with using the filter "Blocked: Show Tasks Not Blocked By Other Tasks" in Queries
Closed, ResolvedPublic

Description

A Query with the field Blocked set to Show Tasks Not Blocked By Other Tasks does not work when at least one of the blocking Subtasks are Resolved. It does however work if all Subtasks are unresolved.

The structure that I have is:

My user story task
    A Subtask for the Java guys
    A Subtask for the JS guys
    A Subtask for QA

I want to have a Query that shows only the actual developer tasks (Subtasks), and not the user story ("grouping task").

With the above structure it works as long as no Subtask has been completed. However; if any of the Subtasks are completed I will see the user story in my view.

Is this a bug according to you? Are there any alternative ways to solve this maybe?

Reproduce

You can see it for yourself by setting the filter mentioned above and looking for this issue, it will not show up. However; if you resolve one of the Subtasks and use the same query you will find the issue in the result.

Event Timeline

quinyx_martin raised the priority of this task from to Needs Triage.
quinyx_martin updated the task description. (Show Details)
quinyx_martin added a project: Maniphest.
quinyx_martin closed subtask T8128: Test Subtask 2 as Resolved.

We have also replicated this in our install.

The expectation is that Show Tasks Not Blocked By Other Tasks should show only tasks with no blockers. As soon as a task has a resolved blocker but other open blockers, it shows up in the query, which is then not as useful for making a task list of "unblocked stuff".

In ManiphestTaskQuery, for blockedTasks === false:

$parts[] = qsprintf(
  $conn,
  'blocked.dst IS NULL OR blockedtask.status NOT IN (%Ls)',
  ManiphestTaskStatus::getOpenStatusConstants());

But it needs to be fancier than that. It can't just look for a single non-open blockedtask.status, it has to ensure that all blocked tasks joined to this are non-open. I'm not sure how to specify that with SQL here.

If nobody pops up with expertise to solve this, I can dig into it for a "My First Phabricator" experience.

it has to ensure that all blocked tasks joined to this are non-open. I'm not sure how to specify that with SQL here.

It seems like it must be done with a subquery. Something like

myTask.Id NOT IN (
SELECT e.src
FROM edge e
INNER JOIN maniphest_task otherTask ON otherTask.Id = e.dst
WHERE e.type = whatever AND otherTask.status IN (someListOfOpenStatuses))

(I may have gotten src and dst mixed up or made similar problem-specific errors; this sketch is not based on any experience with this particular schema, but more the form of the question that we're trying to answer.)

If we just join from task to edge to task, any criterion imposed on the result of that join will only apply to a particular relationship between two tasks. Any row that satisfies the criterion gives a positive answer to a "does there exist a...?" question.. But we have a "does there NOT exist a...?" question here. So I can't see a way for joins without subqueries to do the job.

If i have multiple blocking tasks, and any of them are not resolved i would consider the task blocked and want it to not show based on the "show tasks not blocked by other tasks" filter.

currently if any blocking task is resolved, i see the task using this filter, despite it being blocked by other tasks.

Is there a perspective on doing this any soon? Or too little resources?

I guess you can tell from the history that I put together a patch to fix this and submitted it as a differential revision. I hope it may be considered appropriate for inclusion (and am wiling to do further work on it to bring it up to standard if necessary). Thanks for a great product!

P.S. It's not an April Fool's joke....

Not wanting to nag, but it's been a couple of months since I submitted a diff that fixes this. Would it be possible to include it? Have I done something wrong? Perhaps @chad would know?

@epriestley does reviews from contributors, but I think we likely have hundreds outstanding right now. See Planning.

Thanks for the feedback. I'll sit tight. You know how to reach me if there are any problems or requests related to this. :-)

I'm planning to make these changes:

  • Make this examine only open related tasks, per D15560. While the current behavior is sort of technically "correct" in a literal way, I think it never aligns with user expectation or any reasonable thing users might want to do with these constraints.
  • Make these constraints independent (AND, not OR).
  • Realign language to reflect "parent tasks" and "subtasks", and reflect that this cares about "open tasks".

This probably becomes:

  • With Subtasks
    • (Show All)
    • Show Only Tasks With Open Subtasks
    • Show Only Tasks Without Open Subtasks
  • With Parents
    • (Show All)
    • Show Only Tasks With Open Parents
    • Show Only Tasks Without Open Parents

That said, I'm not sure if some of these options are actually useful. It sort of seems like the only useful queries you can issue are:

  • Show actionable/unblocked tasks ("With Subtasks: Show Only Tasks Without Open Subtasks"). (Is this 99% of the use of this?)
  • Possibly, show blocked root tasks ("With Subtasks: Show Only Tasks With Open Subtasks; With Parents: Show Only Tasks Without Open Parents"), from D15560, although this doesn't seem hugely useful to me. It's not clear to me when you would care about the subtask constraint on this one, vs just finding root tasks.
  • I can't really come up with any time you would query for tasks with open parents. It doesn't really seem especially useful to query for tasks with open subtasks, either.

So we could possibly just make this two checkboxes:

  • Show only tasks with no open subtasks.
  • Show only tasks with no open parents.

I'm not confident enough that the other options are actually useless to really want to remove them, but these dropdowns may sort of be UX traps where we give you two similar-looking options but users want option "A" 99.9% of the time.


This also sort of runs into ApplicationSearch interfaces (mostly Maniphest) being kind of huge/unwieldy. I think parameterized typeaheads bought us a lot of headroom here, but the Maniphest one is still pretty big and these are some of the least useful options on it. No real need to deal with this for now, though.


I'm also planning to introduce "Subtasks Of: [list of tasks]" and "Parents Of: [list of tasks]". These will be hidden by default, like the "ID" selector. They'll become accessible in the UI from the "Task Graph" element, and be accessible via the API or HTTP parameters.

I believe the best way to construct these queries is like this:

With Open Subtasks

... JOIN subtask AS s ON <tasks that are actually subtasks> AND s.status IN (<open statuses>) ... GROUP BY task.phid

Without Open Subtasks

... LEFT JOIN subtask AS s ON <tasks that are actually subtasks> AND s.status IN (<open statuses>) ... WHERE s.phid IS NULL

Where possible, it's usually better to avoid HAVING clauses or subqueries (IN (SELECT ...)). These tend to perform worse than JOIN or LEFT JOIN if you can express a query without them.

Thank you for your attention to this issue!


As a developer, if I'm blocking someone else, I want to know. I would also expect project managers in particular to be interested in what is blocking other stuff, so they can nag/bump priority/assign more resources, etc. to the blocker's assignee. So I believe querying for tasks with open subtasks is useful.

Because of the intermediary join to the edge table I wasn't actually able to get it working without HAVING either, but D16340 should fix the underlying issue here.

epriestley claimed this task.

See also T4788 for some other followup work.

I think it's right to leave the options there, too. Sure, it's two controls, and they don't make much sense to use in certain combinations, but it's totally intuitive (as is the parent/subtask terminology, as opposed to the blocking/blocked terminology).

I also search for blocked tasks (i.e. those with open subtasks), as I have these hidden from most queries but from time to time want to take stock of them. I haven't as yet found a true use for querying based on parent tasks. It's nice in theory to be able to find tasks which are blockers, but it doesn't work in practice in my contexts: it finds tasks which are truly subtasks, i.e. they're just part of a task, not truly holding up work, or which are my own tasks anyway, so it doesn't help me prioritise really (doesn't let me know I'm holding others up).

I feel like truly useful parent task queries would need to query properties of the parents compared to the task itself, e.g.:

  • find tasks with parent tasks assigned to others
  • find tasks with parent tasks which are higher priority than the task itself

These sorts of things could fairly easily be integrated into the current GUI menus if they are useful enough to implement one day, as alternatives to merely "Open", which we have at the moment.