Skip to content

Commit

Permalink
Put Action Scheduler inside our dependencies directory (#4860)
Browse files Browse the repository at this point in the history
  • Loading branch information
engahmeds3ed authored Mar 25, 2022
1 parent 360bd6b commit 22b9aaf
Show file tree
Hide file tree
Showing 89 changed files with 12,924 additions and 4 deletions.
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
},
"process-timeout": 0,
"allow-plugins": {
"composer/installers": true
"composer/installers": true,
"mnsami/composer-custom-directory-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"support": {
Expand All @@ -40,8 +42,7 @@
"require": {
"php": ">=7.0",
"composer/installers": "~1.0",
"monolog/monolog": "^1.0",
"woocommerce/action-scheduler": "^3.4"
"monolog/monolog": "^1.0"
},
"require-dev": {
"php": "^7 || ^8",
Expand All @@ -59,6 +60,7 @@
"psr/container": "1.0.0",
"roave/security-advisories": "dev-master",
"szepeviktor/phpstan-wordpress": "^0.7.0",
"woocommerce/action-scheduler": "^3.4",
"wp-coding-standards/wpcs": "^2",
"wp-media/background-processing": "^1.3",
"wp-media/cloudflare": "^1.0",
Expand Down Expand Up @@ -97,6 +99,7 @@
},
"extra": {
"installer-paths": {
"./inc/Dependencies/ActionScheduler/": ["woocommerce/action-scheduler"],
"vendor/{$vendor}/{$name}/": ["type:wordpress-plugin"],
"./inc/Addon/Cloudflare/": ["wp-media/cloudflare"],
"./inc/Addon/Varnish/": ["wp-media/module-varnish"],
Expand Down
35 changes: 35 additions & 0 deletions inc/Dependencies/ActionScheduler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Action Scheduler - Job Queue for WordPress [![Build Status](https://travis-ci.org/woocommerce/action-scheduler.png?branch=master)](https://travis-ci.org/woocommerce/action-scheduler) [![codecov](https://codecov.io/gh/woocommerce/action-scheduler/branch/master/graph/badge.svg)](https://codecov.io/gh/woocommerce/action-scheduler)

Action Scheduler is a scalable, traceable job queue for background processing large sets of actions in WordPress. It's specially designed to be distributed in WordPress plugins.

Action Scheduler works by triggering an action hook to run at some time in the future. Each hook can be scheduled with unique data, to allow callbacks to perform operations on that data. The hook can also be scheduled to run on one or more occassions.

Think of it like an extension to `do_action()` which adds the ability to delay and repeat a hook.

## Battle-Tested Background Processing

Every month, Action Scheduler processes millions of payments for [Subscriptions](https://woocommerce.com/products/woocommerce-subscriptions/), webhooks for [WooCommerce](https://wordpress.org/plugins/woocommerce/), as well as emails and other events for a range of other plugins.

It's been seen on live sites processing queues in excess of 50,000 jobs and doing resource intensive operations, like processing payments and creating orders, at a sustained rate of over 10,000 / hour without negatively impacting normal site operations.

This is all on infrastructure and WordPress sites outside the control of the plugin author.

If your plugin needs background processing, especially of large sets of tasks, Action Scheduler can help.

## Learn More

To learn more about how to Action Scheduler works, and how to use it in your plugin, check out the docs on [ActionScheduler.org](https://actionscheduler.org).

There you will find:

* [Usage guide](https://actionscheduler.org/usage/): instructions on installing and using Action Scheduler
* [WP CLI guide](https://actionscheduler.org/wp-cli/): instructions on running Action Scheduler at scale via WP CLI
* [API Reference](https://actionscheduler.org/api/): complete reference guide for all API functions
* [Administration Guide](https://actionscheduler.org/admin/): guide to managing scheduled actions via the administration screen
* [Guide to Background Processing at Scale](https://actionscheduler.org/perf/): instructions for running Action Scheduler at scale via the default WP Cron queue runner

## Credits

Action Scheduler is developed and maintained by [Automattic](http://automattic.com/) with significant early development completed by [Flightless](https://flightless.us/).

Collaboration is cool. We'd love to work with you to improve Action Scheduler. [Pull Requests](https://github.com/woocommerce/action-scheduler/pulls) welcome.
65 changes: 65 additions & 0 deletions inc/Dependencies/ActionScheduler/action-scheduler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
/**
* Plugin Name: Action Scheduler
* Plugin URI: https://actionscheduler.org
* Description: A robust scheduling library for use in WordPress plugins.
* Author: Automattic
* Author URI: https://automattic.com/
* Version: 3.4.0
* License: GPLv3
*
* Copyright 2019 Automattic, Inc. (https://automattic.com/contact/)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @package ActionScheduler
*/

if ( ! function_exists( 'action_scheduler_register_3_dot_4_dot_0' ) && function_exists( 'add_action' ) ) {

if ( ! class_exists( 'ActionScheduler_Versions', false ) ) {
require_once __DIR__ . '/classes/ActionScheduler_Versions.php';
add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
}

add_action( 'plugins_loaded', 'action_scheduler_register_3_dot_4_dot_0', 0, 0 );

/**
* Registers this version of Action Scheduler.
*/
function action_scheduler_register_3_dot_4_dot_0() {
$versions = ActionScheduler_Versions::instance();
$versions->register( '3.4.0', 'action_scheduler_initialize_3_dot_4_dot_0' );
}

/**
* Initializes this version of Action Scheduler.
*/
function action_scheduler_initialize_3_dot_4_dot_0() {
// A final safety check is required even here, because historic versions of Action Scheduler
// followed a different pattern (in some unusual cases, we could reach this point and the
// ActionScheduler class is already defined—so we need to guard against that).
if ( ! class_exists( 'ActionScheduler', false ) ) {
require_once __DIR__ . '/classes/abstracts/ActionScheduler.php';
ActionScheduler::init( __FILE__ );
}
}

// Support usage in themes - load this version if no plugin has loaded a version yet.
if ( did_action( 'plugins_loaded' ) && ! doing_action( 'plugins_loaded' ) && ! class_exists( 'ActionScheduler', false ) ) {
action_scheduler_initialize_3_dot_4_dot_0();
do_action( 'action_scheduler_pre_theme_init' );
ActionScheduler_Versions::initialize_latest_version();
}
}
45 changes: 45 additions & 0 deletions inc/Dependencies/ActionScheduler/changelog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
*** Changelog ***

= 3.4.0 - 2021-10-29 =
* Enhancement - Number of items per page can now be set for the Scheduled Actions view (props @ovidiul). #771
* Fix - Do not lower the max_execution_time if it is already set to 0 (unlimited) (props @barryhughes). #755
* Fix - Avoid triggering autoloaders during the version resolution process (props @olegabr). #731 & #776
* Dev - ActionScheduler_wcSystemStatus PHPCS fixes (props @ovidiul). #761
* Dev - ActionScheduler_DBLogger.php PHPCS fixes (props @ovidiul). #768
* Dev - Fixed phpcs for ActionScheduler_Schedule_Deprecated (props @ovidiul). #762
* Dev - Improve actions table indicies (props @glagonikas). #774 & #777
* Dev - PHPCS fixes for ActionScheduler_DBStore.php (props @ovidiul). #769 & #778
* Dev - PHPCS Fixes for ActionScheduler_Abstract_ListTable (props @ovidiul). #763 & #779
* Dev - Adds new filter action_scheduler_claim_actions_order_by to allow tuning of the claim query (props @glagonikas). #773
* Dev - PHPCS fixes for ActionScheduler_WpPostStore class (props @ovidiul). #780

= 3.3.0 - 2021-09-15 =
* Enhancement - Adds as_has_scheduled_action() to provide a performant way to test for existing actions. #645
* Fix - Improves compatibility with environments where NO_ZERO_DATE is enabled. #519
* Fix - Adds safety checks to guard against errors when our database tables cannot be created. #645
* Dev - Now supports queries that use multiple statuses. #649
* Dev - Minimum requirements for WordPress and PHP bumped (to 5.2 and 5.6 respectively). #723

= 3.2.1 - 2021-06-21 =
* Fix - Add extra safety/account for different versions of AS and different loading patterns. #714
* Fix - Handle hidden columns (Tools → Scheduled Actions) | #600.

= 3.2.0 - 2021-06-03 =
* Fix - Add "no ordering" option to as_next_scheduled_action().
* Fix - Add secondary scheduled date checks when claiming actions (DBStore) | #634.
* Fix - Add secondary scheduled date checks when claiming actions (wpPostStore) | #634.
* Fix - Adds a new index to the action table, reducing the potential for deadlocks (props: @glagonikas).
* Fix - Fix unit tests infrastructure and adapt tests to PHP 8.
* Fix - Identify in-use data store.
* Fix - Improve test_migration_is_scheduled.
* Fix - PHP notice on list table.
* Fix - Speed up clean up and batch selects.
* Fix - Update pending dependencies.
* Fix - [PHP 8.0] Only pass action arg values through to do_action_ref_array().
* Fix - [PHP 8] Set the PHP version to 7.1 in composer.json for PHP 8 compatibility.
* Fix - add is_initialized() to docs.
* Fix - fix file permissions.
* Fix - fixes #664 by replacing __ with esc_html__.

= 3.1.6 - 2020-05-12 =
* Change log starts.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* Class ActionScheduler_ActionClaim
*/
class ActionScheduler_ActionClaim {
private $id = '';
private $action_ids = array();

public function __construct( $id, array $action_ids ) {
$this->id = $id;
$this->action_ids = $action_ids;
}

public function get_id() {
return $this->id;
}

public function get_actions() {
return $this->action_ids;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<?php

/**
* Class ActionScheduler_ActionFactory
*/
class ActionScheduler_ActionFactory {

/**
* @param string $status The action's status in the data store
* @param string $hook The hook to trigger when this action runs
* @param array $args Args to pass to callbacks when the hook is triggered
* @param ActionScheduler_Schedule $schedule The action's schedule
* @param string $group A group to put the action in
*
* @return ActionScheduler_Action An instance of the stored action
*/
public function get_stored_action( $status, $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {

switch ( $status ) {
case ActionScheduler_Store::STATUS_PENDING :
$action_class = 'ActionScheduler_Action';
break;
case ActionScheduler_Store::STATUS_CANCELED :
$action_class = 'ActionScheduler_CanceledAction';
if ( ! is_null( $schedule ) && ! is_a( $schedule, 'ActionScheduler_CanceledSchedule' ) && ! is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
$schedule = new ActionScheduler_CanceledSchedule( $schedule->get_date() );
}
break;
default :
$action_class = 'ActionScheduler_FinishedAction';
break;
}

$action_class = apply_filters( 'action_scheduler_stored_action_class', $action_class, $status, $hook, $args, $schedule, $group );

$action = new $action_class( $hook, $args, $schedule, $group );

/**
* Allow 3rd party code to change the instantiated action for a given hook, args, schedule and group.
*
* @param ActionScheduler_Action $action The instantiated action.
* @param string $hook The instantiated action's hook.
* @param array $args The instantiated action's args.
* @param ActionScheduler_Schedule $schedule The instantiated action's schedule.
* @param string $group The instantiated action's group.
*/
return apply_filters( 'action_scheduler_stored_action_instance', $action, $hook, $args, $schedule, $group );
}

/**
* Enqueue an action to run one time, as soon as possible (rather a specific scheduled time).
*
* This method creates a new action with the NULLSchedule. This schedule maps to a MySQL datetime string of
* 0000-00-00 00:00:00. This is done to create a psuedo "async action" type that is fully backward compatible.
* Existing queries to claim actions claim by date, meaning actions scheduled for 0000-00-00 00:00:00 will
* always be claimed prior to actions scheduled for a specific date. This makes sure that any async action is
* given priority in queue processing. This has the added advantage of making sure async actions can be
* claimed by both the existing WP Cron and WP CLI runners, as well as a new async request runner.
*
* @param string $hook The hook to trigger when this action runs
* @param array $args Args to pass when the hook is triggered
* @param string $group A group to put the action in
*
* @return int The ID of the stored action
*/
public function async( $hook, $args = array(), $group = '' ) {
$schedule = new ActionScheduler_NullSchedule();
$action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
return $this->store( $action );
}

/**
* @param string $hook The hook to trigger when this action runs
* @param array $args Args to pass when the hook is triggered
* @param int $when Unix timestamp when the action will run
* @param string $group A group to put the action in
*
* @return int The ID of the stored action
*/
public function single( $hook, $args = array(), $when = null, $group = '' ) {
$date = as_get_datetime_object( $when );
$schedule = new ActionScheduler_SimpleSchedule( $date );
$action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
return $this->store( $action );
}

/**
* Create the first instance of an action recurring on a given interval.
*
* @param string $hook The hook to trigger when this action runs
* @param array $args Args to pass when the hook is triggered
* @param int $first Unix timestamp for the first run
* @param int $interval Seconds between runs
* @param string $group A group to put the action in
*
* @return int The ID of the stored action
*/
public function recurring( $hook, $args = array(), $first = null, $interval = null, $group = '' ) {
if ( empty($interval) ) {
return $this->single( $hook, $args, $first, $group );
}
$date = as_get_datetime_object( $first );
$schedule = new ActionScheduler_IntervalSchedule( $date, $interval );
$action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
return $this->store( $action );
}

/**
* Create the first instance of an action recurring on a Cron schedule.
*
* @param string $hook The hook to trigger when this action runs
* @param array $args Args to pass when the hook is triggered
* @param int $base_timestamp The first instance of the action will be scheduled
* to run at a time calculated after this timestamp matching the cron
* expression. This can be used to delay the first instance of the action.
* @param int $schedule A cron definition string
* @param string $group A group to put the action in
*
* @return int The ID of the stored action
*/
public function cron( $hook, $args = array(), $base_timestamp = null, $schedule = null, $group = '' ) {
if ( empty($schedule) ) {
return $this->single( $hook, $args, $base_timestamp, $group );
}
$date = as_get_datetime_object( $base_timestamp );
$cron = CronExpression::factory( $schedule );
$schedule = new ActionScheduler_CronSchedule( $date, $cron );
$action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
return $this->store( $action );
}

/**
* Create a successive instance of a recurring or cron action.
*
* Importantly, the action will be rescheduled to run based on the current date/time.
* That means when the action is scheduled to run in the past, the next scheduled date
* will be pushed forward. For example, if a recurring action set to run every hour
* was scheduled to run 5 seconds ago, it will be next scheduled for 1 hour in the
* future, which is 1 hour and 5 seconds from when it was last scheduled to run.
*
* Alternatively, if the action is scheduled to run in the future, and is run early,
* likely via manual intervention, then its schedule will change based on the time now.
* For example, if a recurring action set to run every day, and is run 12 hours early,
* it will run again in 24 hours, not 36 hours.
*
* This slippage is less of an issue with Cron actions, as the specific run time can
* be set for them to run, e.g. 1am each day. In those cases, and entire period would
* need to be missed before there was any change is scheduled, e.g. in the case of an
* action scheduled for 1am each day, the action would need to run an entire day late.
*
* @param ActionScheduler_Action $action The existing action.
*
* @return string The ID of the stored action
* @throws InvalidArgumentException If $action is not a recurring action.
*/
public function repeat( $action ) {
$schedule = $action->get_schedule();
$next = $schedule->get_next( as_get_datetime_object() );

if ( is_null( $next ) || ! $schedule->is_recurring() ) {
throw new InvalidArgumentException( __( 'Invalid action - must be a recurring action.', 'action-scheduler' ) );
}

$schedule_class = get_class( $schedule );
$new_schedule = new $schedule( $next, $schedule->get_recurrence(), $schedule->get_first_date() );
$new_action = new ActionScheduler_Action( $action->get_hook(), $action->get_args(), $new_schedule, $action->get_group() );
return $this->store( $new_action );
}

/**
* @param ActionScheduler_Action $action
*
* @return int The ID of the stored action
*/
protected function store( ActionScheduler_Action $action ) {
$store = ActionScheduler_Store::instance();
return $store->save_action( $action );
}
}
Loading

0 comments on commit 22b9aaf

Please sign in to comment.