Skip to content

Unscheduling a recurring action doesn't "stick" if called during the action #1304

Description

@RadGH

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' );
			}
		}
	}
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions