Skip to content

Commit

Permalink
Merge pull request #97 from deliciousbrains/improvements-from-wp-offl…
Browse files Browse the repository at this point in the history
…oad-media

Port forward new features and improvements from WP Offload Media
  • Loading branch information
ianmjones authored Apr 18, 2023
2 parents c6168c3 + b6dd6b7 commit d5ef95c
Show file tree
Hide file tree
Showing 5 changed files with 978 additions and 88 deletions.
8 changes: 0 additions & 8 deletions .phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,7 @@

<!-- TODO: Maybe fix -->
<exclude name="WordPress.WP.CronInterval.ChangeDetected"/>
<exclude name="WordPress.WP.AlternativeFunctions.rand_rand"/>
<exclude name="WordPress.DB.DirectDatabaseQuery.DirectQuery"/>

<!-- TODO: Should fix -->
<exclude name="WordPress.DB.PreparedSQL.InterpolatedNotPrepared"/>
<exclude name="PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket"/>
<exclude name="PEAR.Functions.FunctionCallSignature.MultipleArguments"/>
<exclude name="PEAR.Functions.FunctionCallSignature.CloseBracketLine"/>
<exclude name="Generic.Commenting.DocComment.SpacingAfter"/>
</rule>
<rule ref="WordPress.NamingConventions.PrefixAllGlobals">
<properties>
Expand Down
166 changes: 150 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ __Requires PHP 5.6+__

The recommended way to install this library in your project is by loading it through Composer:

```
```shell
composer require deliciousbrains/wp-background-processing
```

Expand All @@ -27,6 +27,11 @@ Extend the `WP_Async_Request` class:
```php
class WP_Example_Request extends WP_Async_Request {

/**
* @var string
*/
protected $prefix = 'my_plugin';

/**
* @var string
*/
Expand All @@ -45,45 +50,62 @@ class WP_Example_Request extends WP_Async_Request {
}
```

##### `protected $action`
#### `protected $prefix`

Should be set to a unique prefix associated with your plugin, theme, or site's custom function prefix.

#### `protected $action`

Should be set to a unique name.

##### `protected function handle()`
#### `protected function handle()`

Should contain any logic to perform during the non-blocking request. The data passed to the request will be accessible via `$_POST`.

##### Dispatching Requests
#### Dispatching Requests

Instantiate your request:

`$this->example_request = new WP_Example_Request();`
```php
$this->example_request = new WP_Example_Request();
```

Add data to the request if required:

`$this->example_request->data( array( 'value1' => $value1, 'value2' => $value2 ) );`
```php
$this->example_request->data( array( 'value1' => $value1, 'value2' => $value2 ) );
```

Fire off the request:

`$this->example_request->dispatch();`
```php
$this->example_request->dispatch();
```

Chaining is also supported:

`$this->example_request->data( array( 'data' => $data ) )->dispatch();`
```php
$this->example_request->data( array( 'data' => $data ) )->dispatch();
```

### Background Process

Background processes work in a similar fashion to async requests, but they allow you to queue tasks. Items pushed onto the queue will be processed in the background once the queue has been dispatched. Queues will also scale based on available server resources, so higher end servers will process more items per batch. Once a batch has completed, the next batch will start instantly.
Background processes work in a similar fashion to async requests, but they allow you to queue tasks. Items pushed onto the queue will be processed in the background once the queue has been saved and dispatched. Queues will also scale based on available server resources, so higher end servers will process more items per batch. Once a batch has completed, the next batch will start instantly.

Health checks run by default every 5 minutes to ensure the queue is running when queued items exist. If the queue has failed it will be restarted.

Queues work on a first in first out basis, which allows additional items to be pushed to the queue even if it’s already processing.
Queues work on a first in first out basis, which allows additional items to be pushed to the queue even if it’s already processing. Saving a new batch of queued items and dispatching while another background processing instance is already running will result in the dispatch shortcutting out and the existing instance eventually picking up the new items and processing them when it is their turn.

Extend the `WP_Background_Process` class:

```php
class WP_Example_Process extends WP_Background_Process {

/**
* @var string
*/
protected $prefix = 'my_plugin';

/**
* @var string
*/
Expand Down Expand Up @@ -122,23 +144,29 @@ class WP_Example_Process extends WP_Background_Process {
}
```

##### `protected $action`
#### `protected $prefix`

Should be set to a unique prefix associated with your plugin, theme, or site's custom function prefix.

#### `protected $action`

Should be set to a unique name.

##### `protected function task( $item )`
#### `protected function task( $item )`

Should contain any logic to perform on the queued item. Return `false` to remove the item from the queue or return `$item` to push it back onto the queue for further processing. If the item has been modified and is pushed back onto the queue the current state will be saved before the batch is exited.

##### `protected function complete()`
#### `protected function complete()`

Optionally contain any logic to perform once the queue has completed.

##### Dispatching Processes
#### Dispatching Processes

Instantiate your process:

`$this->example_process = new WP_Example_Process();`
```php
$this->example_process = new WP_Example_Process();
```

**Note:** You must instantiate your process unconditionally. All requests should do this, even if nothing is pushed to the queue.

Expand All @@ -152,7 +180,113 @@ foreach ( $items as $item ) {

Save and dispatch the queue:

`$this->example_process->save()->dispatch();`
```php
$this->example_process->save()->dispatch();
```

#### Background Process Status

A background process can be queued, processing, paused, cancelled, or none of the above (not started or has completed).

##### Queued

To check whether a background process has queued items use `is_queued()`.

```php
if ( $this->example_process->is_queued() ) {
// Do something because background process has queued items, e.g. add notice in admin UI.
}
```

##### Processing

To check whether a background process is currently handling a queue of items use `is_processing()`.

```php
if ( $this->example_process->is_processing() ) {
// Do something because background process is running, e.g. add notice in admin UI.
}
```

##### Paused

You can pause a background process with `pause()`.

```php
$this->example_process->pause();
```

The currently processing batch will continue until it either completes or reaches the time or memory limit. At that point it'll unlock the process and either complete the batch if the queue is empty, or perform a dispatch that will result in the handler removing the healthcheck cron and firing a "paused" action.

To check whether a background process is currently paused use `is_paused()`.

```php
if ( $this->example_process->is_paused() ) {
// Do something because background process is paused, e.g. add notice in admin UI.
}
```

You can perform an action in response to background processing being paused by handling the "paused" action for the background process's identifier ($prefix + $action).

```php
add_action( 'my_plugin_example_process_paused', function() {
// Do something because background process is paused, e.g. add notice in admin UI.
});
```

You can resume a background process with `resume()`.

```php
$this->example_process->resume();
```

You can perform an action in response to background processing being resumed by handling the "resumed" action for the background process's identifier ($prefix + $action).

```php
add_action( 'my_plugin_example_process_resumed', function() {
// Do something because background process is resumed, e.g. add notice in admin UI.
});
```

##### Cancelled

You can cancel a background process with `cancel()`.

```php
$this->example_process->cancel();
```

The currently processing batch will continue until it either completes or reaches the time or memory limit. At that point it'll unlock the process and either complete the batch if the queue is empty, or perform a dispatch that will result in the handler removing the healthcheck cron, deleting all batches of queued items and firing a "cancelled" action.

To check whether a background process is currently cancelled use `is_cancelled()`.

```php
if ( $this->example_process->is_cancelled() ) {
// Do something because background process is cancelled, e.g. add notice in admin UI.
}
```

You can perform an action in response to background processing being cancelled by handling the "cancelled" action for the background process's identifier ($prefix + $action).

```php
add_action( 'my_plugin_example_process_cancelled', function() {
// Do something because background process is paused, e.g. add notice in admin UI.
});
```

The "cancelled" action fires once the queue has been cleared down and cancelled status removed. After which `is_cancelled()` will no longer be true as the background process is now dormant.

##### Active

To check whether a background process has queued items, is processing, is paused, or is cancelling, use `is_active()`.

```php
if ( $this->example_process->is_active() ) {
// Do something because background process is active, e.g. add notice in admin UI.
}
```

If a background process is not active, then it either has not had anything queued yet and not started, or has finished processing all queued items.

### BasicAuth

Expand Down
28 changes: 25 additions & 3 deletions classes/wp-async-request.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ protected function get_post_args() {
'timeout' => 0.01,
'blocking' => false,
'body' => $this->data,
'cookies' => $_COOKIE,
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
'cookies' => $_COOKIE, // Passing cookies ensures request is performed as initiating user.
'sslverify' => apply_filters( 'https_local_ssl_verify', false ), // Local requests, fine to pass false.
);

/**
Expand All @@ -158,6 +158,8 @@ protected function get_post_args() {
* Maybe handle a dispatched request.
*
* Check for correct nonce and pass to handler.
*
* @return void|mixed
*/
public function maybe_handle() {
// Don't lock up other requests while processing.
Expand All @@ -167,7 +169,27 @@ public function maybe_handle() {

$this->handle();

wp_die();
return $this->maybe_wp_die();
}

/**
* Should the process exit with wp_die?
*
* @param mixed $return What to return if filter says don't die, default is null.
*
* @return void|mixed
*/
protected function maybe_wp_die( $return = null ) {
/**
* Should wp_die be used?
*
* @return bool
*/
if ( apply_filters( $this->identifier . '_wp_die', true ) ) {
wp_die();
}

return $return;
}

/**
Expand Down
Loading

0 comments on commit d5ef95c

Please sign in to comment.