├── README.md
└── action-scheduler-timeout-monitor.php
/README.md:
--------------------------------------------------------------------------------
1 | ## Action Scheduler Timeout Monitor
2 |
3 | If a scheduled action runs for more than its allocated time (`action_scheduler_failure_period`) the `ActionScheduler_QueueCleaner` will mark the action as failed and log the nondescript error `action timed out after 300 seconds`. Because this cleaning event occurs in another PHP instance and separate process there's no stack trace which can be included as part of this error.
4 |
5 | This mini-extension keeps a record of where the action got caught up to help troubleshoot what's taking the action more than the 5 minutes (default) allowed.
6 |
7 | This plugin makes use of the resource intensive WP `'all'` action and therefore it is not recommended to have this plugin active for any longer than necessary.
8 |
9 | ### Installation
10 |
11 | 1. Upload the plugin's files to the `/wp-content/plugins/` directory of your WordPress site
12 | 1. Activate the plugin through the **Plugins** menu in WordPress
13 |
14 | #### License
15 |
16 | This plugin is released under [GNU General Public License v3.0](http://www.gnu.org/licenses/gpl-3.0.html).
17 |
18 | ---
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/action-scheduler-timeout-monitor.php:
--------------------------------------------------------------------------------
1 | .
24 | *
25 | * @version 1.0
26 | * @package Action Scheduler Timeout Monitor
27 | * @author Prospress
28 | */
29 |
30 | if ( ! defined( 'ABSPATH' ) ) {
31 | exit; // Exit if accessed directly
32 | }
33 |
34 | class Action_Scheduler_Timeout_Monitor {
35 |
36 | protected static $action_id = null;
37 | protected static $start_time = null;
38 | protected static $timeout_time = null;
39 |
40 | /**
41 | * Attach callbacks
42 | *
43 | * @since 1.0
44 | */
45 | public static function init() {
46 | add_action( 'action_scheduler_before_execute', __CLASS__ . '::start_monitoring_action', 10 );
47 | add_action( 'action_scheduler_after_execute', __CLASS__ . '::stop_monitoring_action', 10 );
48 | }
49 |
50 | /**
51 | * Attach an 'all' action callback for monitoring execution times.
52 | *
53 | * @param int $action_id
54 | * @since 1.0
55 | */
56 | public static function start_monitoring_action( $action_id ) {
57 | self::$action_id = $action_id;
58 | self::$start_time = microtime( true );
59 | self::$timeout_time = self::$start_time + apply_filters( 'action_scheduler_failure_period', 5 * MINUTE_IN_SECONDS );
60 |
61 | add_action( 'all', __CLASS__ . '::track_action_execution_time', 0 );
62 | }
63 |
64 | /**
65 | * Detach 'all' action callbacks
66 | *
67 | * @since 1.0
68 | */
69 | public static function stop_monitoring_action() {
70 | self::$action_id = self::$start_time = self::$timeout_time = null;
71 |
72 | remove_action( 'all', __CLASS__ . '::track_action_execution_time', 0 );
73 | }
74 |
75 | /**
76 | * Detach 'all' action callbacks
77 | *
78 | * @since 1.0
79 | */
80 | public static function track_action_execution_time( $value ) {
81 | $current_time = microtime( true );
82 |
83 | if ( $current_time + 0.1 > self::$timeout_time ) {
84 | throw new Exception( sprintf( 'Scheduled action %s was about to timeout after %s', self::$action_id, $current_time - self::$start_time ) );
85 | }
86 |
87 | return $value;
88 | }
89 | }
90 | Action_Scheduler_Timeout_Monitor::init();
91 |
--------------------------------------------------------------------------------