-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Display and delete invalid background jobs #40846
Conversation
397c3a7
to
202f875
Compare
@cdamken I noticed that How do installations usually cleanup left-behind background jobs? |
💥 Acceptance tests pipeline apiSharees-maria10.2-php7.4 failed. The build has been cancelled. |
@@ -350,4 +370,26 @@ public function listJobs(\Closure $callback) { | |||
} | |||
$result->closeCursor(); | |||
} | |||
|
|||
public function listInvalidJobs(): array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better if we use a listJobsIncludingInvalid(\Closure $callback)
method instead (I'm not sure about the callback parameter, so maybe we can remove it). The behavior can be copied from the listJobs(...)
method, but taking into account the invalid jobs.
The new listJobsIncludingInvalid(...)
method will return a list of valid jobs and another list of invalid jobs, any of them could be empty.
This should be a better approach because the "status" background job only needs to do one query to the DB, and it also needs to query the DI once too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored, removing listInvalidJobs
, and made listJobs
take an optional parameter $onlyInvalidJobs
The "tricky" thing is that for invalid jobs it is not possible to create a $job
that is really the class of the invalid job. So I create it as a CommandJob
class, and the callback has a 2nd parameter where it can pass the "invalid" class name as a string, which ends up in the command output. (It is not helpful if the command output always just says CommandJob
for invalid jobs)
See PR #40848 - is that a better thing to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd still keep my idea.
The reason to use a different method is to avoid modifying the current listJobs
method. As you've said, we can't build a job from an invalid class, so we can't return anything useful (adding a FakeJob
might be cumbersome)
By adding a new method, we have the flexibility to return anything we want. For this particular case, we can return a list of IJob
for the valid jobs AND a list of DB rows for the invalid jobs.
We could also return all the DB rows, but it might be less useful because we can't build the jobs if needed from outside the JobList
@@ -240,6 +240,26 @@ public function getById($id) { | |||
} | |||
} | |||
|
|||
/** | |||
* @param int $id | |||
* @return bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
returning the whole row seems better because it gives more information at the same price, so you can either return the row, or null if the row doesn't exists. Maybe it shouldn't be called jobIdExists
then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jobIdExists
is only used by Delete.php
. Delete.php
has a Job Id and only needs to know a true
/false
answer about if the Job Id exists. Then it deletes the job. It does not use any information about the job.
But if we add some interactive confirmation dialog, then it would be useful to have the data about the job.
I will make a proposal on top of this for some sort of "confirmation dialog" and "force" option.
@@ -51,8 +51,7 @@ protected function configure() { | |||
protected function execute(InputInterface $input, OutputInterface $output): int { | |||
$id = $input->getArgument('Job ID'); | |||
|
|||
$job = $this->jobList->getById($id); | |||
if ($job === null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we include a safety check somehow? Maybe preventing deleting valid jobs unless explicitly asked. Something like "This job is currently valid. Use the --force option if you want to delete it"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current code deletes a valid job without confirmation.
If a --force
option is to be a requirement, then that is a new requirement.
The current code does not find an invalid job (a job that is in the database but the class of the job no longer exists, cannot be found). And so there is no way to delete an invalid job. This change just allows invalid jobs to be found and deleted.
dc1cbec
to
7c09499
Compare
7c09499
to
526ecee
Compare
62702ba
to
e0c9008
Compare
e0c9008
to
f1de667
Compare
@jvillafanez please review again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Callback documentation is important. We might not need to change the code (maybe for the error handling in the callbacks), but we need to ensure the expectations and responsibilities are clear between what core provides and the callbacks.
* | ||
* @return void | ||
* @since 10.2.0 | ||
*/ | ||
public function listJobs(\Closure $callback); | ||
|
||
/** | ||
* iterate over all jobs in the queue, including invalid jobs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need documentation about the callbacks. What parameters are expected? Can we change the parameters from the callback somehow? What should the callback return? How the errors are expected to be handled?
For example, the $validJobCallback
could use an IJob
as parameter, or a DB row, or multiple parameters such as a DB row plus an output stream (in order for you to write in the provided output stream instead of the stdout, for example); the $validJobCallback
could also return true
(a boolean) to stop the listing because I'm only interested in the first 10 jobs.
The error handling is also important because we need to know who need to handle any error that could happen inside the callback. If it needs to be handled by the callback, we need documentation because the callback might need to have a "catch all" policy not to leak any exception to the outside.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added documentation about the callbacks. I added it to the original listJobs
method also - that did not document the existing code.
My additional code does the same sort of thing as listJobs
already did. I reverse-engineered documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kind of weird that the validJobCallback
can stop the iteration for the invalidJobCallback
.... I guess it's ok because the caller should be aware, and it's up to him to setup the callbacks correctly.
f1de667
to
0a1147d
Compare
Kudos, SonarCloud Quality Gate passed! |
* | ||
* @return void | ||
* @since 10.2.0 | ||
*/ | ||
public function listJobs(\Closure $callback); | ||
|
||
/** | ||
* iterate over all jobs in the queue, including invalid jobs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kind of weird that the validJobCallback
can stop the iteration for the invalidJobCallback
.... I guess it's ok because the caller should be aware, and it's up to him to setup the callbacks correctly.
Description
If I have background jobs that are from an old version of an app (their associated class no longer exists) or are from an app that is now disabled (and maybe deleted from the server) then
occ background:queue:status
does not show them (the code of that command only reports background jobs where the class of the job can be instantiated). So I can't find out the job id of those invalid jobs.Even if I have found out the job id, if I try
occ background:queue:delete
with the job id, it tells me the job id is not known, because the code only finds a job id if it has a class that can be instantiated.It's a PITA.
This PR adds:
occ background:queue:status --display-invalid-jobs
so that the user can see the invalid jobs.
And the
occ background:queue:delete
is adjusted so that, if the job id exists then it is deleted (whether or not the job is valid).How Has This Been Tested?
TBD
Types of changes
Checklist: