I have a plugin that upon creating a post, schedules a recurring action with an arg containing that post's ID. The action should continue running at its specified interval until my arbitrary processing is completed. It may take several iterations.
During the process I check if there is any more work to do. If not, I want to unschedule the recurring action so it stops running. The problem is neither as_unschedule_all_actions or as_unschedule_action seems to work. The action remains until I delete it manually.
I discovered that if I set up a custom url to unschedule the action, visiting that url directly does work.
So the problem is you can't unschedule an action while the same action is currently running.
I think the problem is that it DOES remove the action correctly, but it immediately adds a new one back in after the action finishes, because it is a recurring action.
My workaround was instead of unscheduling the action immediately, to add it to a queue and instead unschedule it during the "shutdown" event at the end of the request. This solved the problem!
I think this should be fixed so that if you unschedule an action that is actively running, it should prevent the action from rescheduling itself. That is the point of unscheduling the action, isn't it? It just seems weird it doesn't work that way.
Below is the relevant code from my plugin, including the workaround. The "unschedule_test" method originally had the "as_unschedule_all_actions" function in it directly, but that didn't unschedule it. Moving it to the "shutdown" function is the key.
class AAFT_Registry {
private static $tests_to_unschedule = [];
private function __construct() {
add_action( 'shutdown', array( $this, 'on_shutdown_unschedule_queued_tests' ) );
}
public static function schedule_test( $test_id ) {
if ( get_post_type($test_id) != 'aaft_test' ) return false;
as_schedule_recurring_action(
time(),
30,
'aaft_process_test',
array( $test_id ),
'aaft'
);
}
public static function unschedule_test( $test_id ) {
// This line does not work if called while the action is running!
// -- as_unschedule_all_actions( 'aaft_process_test', array( $test_id ), 'aaft' );
// Workaround: Queue it to be unscheduled during 'shutdown'
self::$tests_to_unschedule[] = $test_id;
}
public function on_shutdown_unschedule_queued_tests() {
if ( !empty( self::$tests_to_unschedule ) ) {
foreach ( self::$tests_to_unschedule as $test_id ) {
as_unschedule_all_actions( 'aaft_process_test', array( $test_id ), 'aaft' );
}
}
}
}
I have a plugin that upon creating a post, schedules a recurring action with an arg containing that post's ID. The action should continue running at its specified interval until my arbitrary processing is completed. It may take several iterations.
During the process I check if there is any more work to do. If not, I want to unschedule the recurring action so it stops running. The problem is neither
as_unschedule_all_actionsoras_unschedule_actionseems to work. The action remains until I delete it manually.I discovered that if I set up a custom url to unschedule the action, visiting that url directly does work.
So the problem is you can't unschedule an action while the same action is currently running.
I think the problem is that it DOES remove the action correctly, but it immediately adds a new one back in after the action finishes, because it is a recurring action.
My workaround was instead of unscheduling the action immediately, to add it to a queue and instead unschedule it during the "shutdown" event at the end of the request. This solved the problem!
I think this should be fixed so that if you unschedule an action that is actively running, it should prevent the action from rescheduling itself. That is the point of unscheduling the action, isn't it? It just seems weird it doesn't work that way.
Below is the relevant code from my plugin, including the workaround. The "unschedule_test" method originally had the "as_unschedule_all_actions" function in it directly, but that didn't unschedule it. Moving it to the "shutdown" function is the key.