/action-scheduler-job-framework

Primary LanguagePHPGNU General Public License v3.0GPL-3.0

Action Scheduler Job Framework

Requirements

  • PHP 7.0+
  • Jetpack Autoloader - Required to ensure the latest version of the framework is used in case multiple plugins have it as a dependency

Versioning & breaking changes

This package follows Semver for versioning.

This framework may receive breaking changes at the moment while it is only used in the Facebook for WooCommerce plugin. However, once we use it in another plugin we will need to reject all breaking changes.

Installation

The framework should be installed via Composer.

  1. Add the following to your project's composer.json file:
{
  "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/woocommerce/action-scheduler-job-framework"
    }
  ],
  "require": {
    "woocommerce/action-scheduler-job-framework": "^2.0.0"
  }
}
  1. Then run composer update

Chained Jobs

A "chained job" is a kind of batched job that creates follow-up actions in a chain until a set of items has been processed.

Each "batch" in the job is a separate "scheduled action". Each batch is numbered and should be limited to process a set number of items.

Methods

  • ::handle_start() - Runs before a job instance starts.
  • ::handle_end() - Runs after a job instance ends.
  • ::get_items_for_batch() - Gets a set of items for the batch to process.
  • ::process_item() - Processes a single item.
  • ::get_name() - Get the unique name/ID of the job.
  • ::get_number_of_items_processed() - Get the number of items that have been processed by the currently running instance of the job.
  • ::is_running() - Check if this job is currently running. Checks if there is any "start" or "batch" actions pending or in-progress for the job.

Example:

class GenerateProductFeed extends Automattic\WooCommerce\ActionSchedulerJobFramework\AbstractChainedJob {

	use Automattic\WooCommerce\ActionSchedulerJobFramework\Utilities\BatchQueryOffset;

	/**
	 * Runs before starting the job.
	 */
	protected function handle_start() {
		// Optionally do something when starting the job.
	}

	/**
	 * Runs after the finishing the job.
	 */
	protected function handle_end() {
		// Optionally do something when ending the job.
	}

	/**
	 * Get a set of items for the batch.
	 *
	 * NOTE: when using an OFFSET based query to retrieve items it's recommended to order by the item ID while
	 * ASCENDING. This is so that any newly added items will not disrupt the query offset.
	 *
	 * @param int   $batch_number The batch number increments for each new batch in the job cycle.
	 * @param array $args         The args for the job.
	 *
	 * @throws Exception On error. The failure will be logged by Action Scheduler and the job chain will stop.
	 */
	protected function get_items_for_batch( int $batch_number, array $args ): array {
		$product_args = [
			'fields'         => 'ids',
			'post_status'    => 'publish',
			'post_type'      => [ 'product', 'product_variation' ],
			'posts_per_page' => $this->get_batch_size(),
			'offset'         => $this->get_query_offset( $batch_number ),
			'orderby'        => 'ID',
			'order'          => 'ASC',
		];

		$query = new WP_Query( $product_args );
		return $query->posts;
	}

	/**
	 * Process a single item.
	 *
	 * @param string|int|array $item A single item from the get_items_for_batch() method.
	 * @param array            $args The args for the job.
	 *
	 * @throws Exception On error. The failure will be logged by Action Scheduler and the job chain will stop.
	 */
	protected function process_item( $item, array $args ) {
		// Process each item here.
	}

	/**
	 * Get the name/slug of the job.
	 *
	 * @return string
	 */
	public function get_name(): string {
		return 'generate_feed';
	}

	/**
	 * Get the name/slug of the plugin that owns the job.
	 *
	 * @return string
	 */
	public function get_plugin_name(): string {
		return 'facebook_for_woocommerce';
	}

}


add_action( 'init', function() {
    $job = new GenerateProductFeed(
        new \Automattic\WooCommerce\ActionSchedulerJobFramework\Proxies\ActionScheduler()
    );
    $job->init();
    
    // Start the job if it's not already running
    if ( ! $job->is_running() ) {
        $job->queue_start();
    }
});