Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multiple runs per task #667

Merged
merged 3 commits into from
Jul 21, 2022

Conversation

promulo
Copy link
Contributor

@promulo promulo commented Jul 11, 2022

Currently, only one task run can be active (running or paused) at a given time. This PR intends to add support for multiple runs for a given task to the gem.

The approach here was to introduce as least disruption as possible and implement minimal changes to both backend and UI, still adhering to current patterns. The dashboard and individual task pages were tweaked a bit in order to allow displaying more than one run for the same task. This means we should rely less on the concept of last run and more on active runs.

I haven't experienced issues when manually testing this. Multiple task runs can be triggered using the usual Run button and individual runs can be paused and resumed accordingly.

This is how the "new" index page looks like with these changes (the list of "New Tasks" and "Completed Tasks" look the same):

image

The above screenshot shows a real example of two runs of the same task being active at the same time.

As for the individual task page, this is the current state:

image

That is an example of a task with multiple active runs listed on its own page.

I will keep pushing changes to this branch but wanted to have some early feedback. The proposed UI might not be what we want. I'm also considering splitting this in separate backend/frontend PRs if that favors iteration.

Thanks!

@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch 2 times, most recently from bac20d2 to e4be6c9 Compare July 15, 2022 12:29
@promulo promulo self-assigned this Jul 15, 2022
@dirceu
Copy link

dirceu commented Jul 18, 2022

Nice!

Couple of ideas for the UI:

  1. On the individual task page, we could make the source code collapsable—maybe with a "Review code" or "See code" button right besides "Run". Especially for "reusable" tasks with multiple runs, the code is important but if you have multiple concurrent runs, it might be easier to follow their progress if you can start with the code already collapsed.
  2. Speaking of following progress, I wonder if it would make sense to show the run ID somewhere to make it easier to identify what already finished. That could make it easier to identify how things are moving if, for example, if the third run out of 7 you started finished early.

@etiennebarrie
Copy link
Member

Regarding the UI failures, most of them can be fixed easily:

  • we don't need to check the Run button is disabled anymore
  • the pause/cancel buttons should be available when the task is enqueued

I pushed commits for these.
The last issue remaining is dealing with double enqueues. We should be able to fix the test to first create a run before opening a new tab.

@promulo promulo changed the title [WIP/PoC] Add support for multiple runs per task Add support for multiple runs per task Jul 18, 2022
@promulo
Copy link
Contributor Author

promulo commented Jul 18, 2022

Pushed a fix for the failing test.

Do we think this UI be good enough as a first iteration of this feature? We could then build on top of it for a better UX.

@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch 2 times, most recently from f799806 to f6323da Compare July 18, 2022 15:55
Copy link
Contributor

@adrianna-chang-shopify adrianna-chang-shopify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature is SO SO exciting to see! 😍 A couple small comments, but the code looks good and so does the tophat!

I think we'll need to update the docs for a couple methods now that the "single-run-per-task" assumption no longer applies (some of the methods in TaskData might need to have their descriptions tweaked, like #available_tasks).

One thing I noticed while tophatting that we might want to tweak: currently, a task's status is determined by using the status of the last run:

def status
last_run&.status || "new"
end

This leads to situations like this:
Screen Shot 2022-07-18 at 12 08 41 PM

Where the last run may have a terminal status (succeeded, cancelled, etc.) but prior runs are still in an active state. Does it make sense here to consider the status of the last active run, if any, instead of just the last created run for the task? If there are multiple runs with active statuses (for example, one is paused, one is interrupted, one is running), should the task potentially report on all of these?

app/models/maintenance_tasks/task_data.rb Outdated Show resolved Hide resolved
test/dummy/db/schema.rb Outdated Show resolved Hide resolved
test/dummy/db/schema.rb Outdated Show resolved Hide resolved
test/dummy/db/schema.rb Outdated Show resolved Hide resolved
@promulo
Copy link
Contributor Author

promulo commented Jul 18, 2022

Thanks a lot @adrianna-chang-shopify, those are all fair points. I'll update the PR soon.

@promulo
Copy link
Contributor Author

promulo commented Jul 18, 2022

One thing I noticed while tophatting that we might want to tweak: currently, a task's status is determined by using the status of the last run [...] Does it make sense here to consider the status of the last active run, if any, instead of just the last created run for the task?

@adrianna-chang-shopify Nice catch! I do think it makes sense and we could keep it simple for this first iteration. Maybe in the future we drop the label from the task itself and add it to each run? 🤔

@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch from cae6bae to 83b402d Compare July 19, 2022 08:52
Copy link
Contributor

@adrianna-chang-shopify adrianna-chang-shopify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! I do think it makes sense and we could keep it simple for this first iteration. Maybe in the future we drop the label from the task itself and add it to each run? 🤔

Yes, absolutely we can hold off for this iteration! It was just something that popped into my head while tophatting, but we might want to experiment with a couple different options to see which one is the most user friendly.

One last comment -- it won't let me add it directly into the changes because the code wasn't changed in this PR, but I think we also want to modify #category to align with the changes made to #status, and consider a task "active" if any of its runs are currently active:

diff --git a/app/models/maintenance_tasks/task_data.rb b/app/models/maintenance_tasks/task_data.rb
index c82a27f..41f9159 100644
--- a/app/models/maintenance_tasks/task_data.rb
+++ b/app/models/maintenance_tasks/task_data.rb
@@ -143,7 +143,7 @@ module MaintenanceTasks
     #
     # @return [Symbol] the category of the Task.
     def category
-      if last_run.present? && last_run.active?
+      if active_runs.any?
         :active
       elsif last_run.nil?
         :new

Great work on this! ❤️

@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch 2 times, most recently from 02f39ff to e7461bf Compare July 19, 2022 13:23
@promulo
Copy link
Contributor Author

promulo commented Jul 19, 2022

@adrianna-chang-shopify After discussing with @etiennebarrie we thought it would be a good idea to already drop the label from the title in the #show page and rely only on individual runs' status labels.

image

That would avoid some confusion in the index page and we can keep the current implementation for TaskData#category and TaskData#status. Wdyt?

P.S.: Postgres is being funny with the ordering, that's why the build is red. Working on it.

@adrianna-chang-shopify
Copy link
Contributor

After discussing with @etiennebarrie we thought it would be a good idea to already drop the label from the title in the #show page and rely only on individual runs' status labels.

Yep, I'm OK with this too! 👍

@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch from 5abdb2b to 50c9717 Compare July 19, 2022 14:10
@promulo promulo marked this pull request as ready for review July 19, 2022 14:18
test/dummy/db/schema.rb Outdated Show resolved Hide resolved
app/controllers/maintenance_tasks/tasks_controller.rb Outdated Show resolved Hide resolved
@@ -93,17 +103,23 @@ def last_run
@last_run = runs.first
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to remove that concept of a last_run since now we either want the active run or the completed runs. From the index, we go through TaskData.available_tasks, and the TaskData objects are initialized with a Run each (or nil).

We need to handle the case of TaskData.find, which right now is used to cause a 404 in tasks#show, but since we don't really want that usage of last_run, and completed_runs is paginated (and maybe one day active_runs too?), it can be hard to know whether there is a Run or not for the 404 to be paginated.

Maybe we could pass the cursor to the task data, and it would build the RunsPage, that way we would load the active runs, load the paginated completed runs, and if we don't have any of these, we could cause the 404. Alternatively we could add a line to the controller, so that the exception leading to the 404 is raised at the end of the controller action, once we know if there's any run or not because we've loaded the active and completed runs.
[These two solutions would add a 404 where there's not now: if you "paginate" past the last cursor of a deleted task, right now we will find the last run and show it at the top anyway, but if we only rely on loaded data to know whether to 404, we will get a 404. But it's not much of a problem, the pagination would never get you there, only by changing the cursor in the URL to a value before which there's no run would you get that 404.]

We could also live with an additional query just to check the existence of a run, but I find that a bit sad, since we're loading the active/completed runs anyway, we could rely on that.

Copy link
Contributor Author

@promulo promulo Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed TaskData#last_run as a method but kept an alias for the old references. The instance variable is now called related_run. Updating all references can be done in a follow-up PR.

Copy link
Contributor

@adrianna-chang-shopify adrianna-chang-shopify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty close to me, although there's still some confusion on my end about ordering the indexes.

I think @etiennebarrie had also mentioned getting rid of the concept of last_run on TaskData, now that we're storing active / completed runs?

test/dummy/db/schema.rb Outdated Show resolved Hide resolved
app/models/maintenance_tasks/task_data.rb Outdated Show resolved Hide resolved
@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch 2 times, most recently from 8944326 to b3e1df1 Compare July 21, 2022 11:35
Copy link
Member

@etiennebarrie etiennebarrie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good!

app/models/maintenance_tasks/runner.rb Outdated Show resolved Hide resolved
app/models/maintenance_tasks/task_data.rb Outdated Show resolved Hide resolved
app/models/maintenance_tasks/task_data.rb Show resolved Hide resolved
app/models/maintenance_tasks/task_data.rb Show resolved Hide resolved
app/models/maintenance_tasks/task_data.rb Outdated Show resolved Hide resolved
app/models/maintenance_tasks/task_data.rb Show resolved Hide resolved
@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch from b3e1df1 to ac49bb7 Compare July 21, 2022 13:25
promulo and others added 3 commits July 21, 2022 15:42
Co-Authored-By: Étienne Barrié <[email protected]>
Co-Authored-By: Étienne Barrié <[email protected]>
@promulo promulo force-pushed the paulo/multiple-active-runs-per-task branch from ac49bb7 to fef42ca Compare July 21, 2022 13:45
Copy link
Contributor

@adrianna-chang-shopify adrianna-chang-shopify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, great work on this! I chatted with Étienne about some changes that will be made in a follow up PR, but I think this is good to go in the meantime :shipit:

Copy link
Member

@etiennebarrie etiennebarrie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@promulo promulo merged commit 805b3e3 into main Jul 21, 2022
@promulo promulo deleted the paulo/multiple-active-runs-per-task branch July 21, 2022 15:30
@shopify-shipit shopify-shipit bot temporarily deployed to rubygems September 26, 2022 13:57 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants