| 1 |
# Actual webserver queue/health integration |
| 2 |
|
| 3 |
Run from a machine with Docker Compose and Python 3. Supply an **unconfigured, |
| 4 |
disposable** copy of WordPress core and WooCommerce. Do not copy a database, |
| 5 |
`wp-config.php`, uploads, tokens or other plugins from a customer site. |
| 6 |
|
| 7 |
For example, copy the core and WooCommerce code from an existing local Docker |
| 8 |
development stack (replace the container name as appropriate): |
| 9 |
|
| 10 |
```sh |
| 11 |
mkdir -p /tmp/sync-basalam-matrix/site/wp-content/plugins |
| 12 |
docker exec basalam-wordpress-local-wordpress-1 \ |
| 13 |
tar -C /var/www/html --exclude=wp-config.php --exclude=wp-content --exclude=.htaccess -cf - . \ |
| 14 |
| tar -C /tmp/sync-basalam-matrix/site -xf - |
| 15 |
docker exec basalam-wordpress-local-wordpress-1 \ |
| 16 |
tar -C /var/www/html/wp-content/plugins -cf - woocommerce \ |
| 17 |
| tar -C /tmp/sync-basalam-matrix/site/wp-content/plugins -xf - |
| 18 |
python3 tests/integration/webservers/run.py \ |
| 19 |
--site-dir /tmp/sync-basalam-matrix/site \ |
| 20 |
--results /tmp/sync-basalam-matrix/results |
| 21 |
``` |
| 22 |
|
| 23 |
The runner creates its own MariaDB volume/network and installs WordPress, |
| 24 |
WooCommerce and this checkout's plugin. It runs each backend sequentially because |
| 25 |
the real MySQL advisory lock is global to the database server. The server/PHP |
| 26 |
images are pinned to the tested digests. Ports 8141–8144 bind to loopback only. |
| 27 |
Only this stack's containers and disposable DB volume are removed on completion. |
| 28 |
The supplied disposable site directory and report files remain available. |
| 29 |
|
| 30 |
`--servers nginx caddy` selects a subset. `--keep` retains test containers after |
| 31 |
a failure for debugging; a subsequent runner invocation reconfigures their |
| 32 |
ephemeral token. Use only one matrix run at a time. |
| 33 |
|
| 34 |
The control MU plugin requires a local WordPress environment and an ephemeral |
| 35 |
token on each control request. It cannot be enabled by an ordinary production |
| 36 |
plugin activation. Its installer requires CLI, the local environment and the |
| 37 |
matrix token. Remote HTTP calls and email are blocked; only real loopback HTTP |
| 38 |
to the tested WordPress instance is allowed. |
| 39 |
|
| 40 |
The installed plugin's unmodified AJAX handler, job runner, queue table, executor, |
| 41 |
registry and MySQL locks are exercised over HTTP. A small local fixture job |
| 42 |
performs success, explicit failure, delayed execution or a real PHP fatal. These |
| 43 |
tests do **not** call Basalam's external API or fabricate customer orders. |
| 44 |
Product/order semantics have their separate integration/unit tests. |
| 45 |
|
| 46 |
Scenarios include nonce rejection/acceptance, successful cleanup, fixture API 422 |
| 47 |
separation, real nonblocking dispatch with a caller that disconnects, four |
| 48 |
concurrent HTTP workers, slow-worker exclusion, SIGKILL of the actual PHP worker, |
| 49 |
independent detection on a subsequent admin request, notice permissions, |
| 50 |
restart persistence, stale recovery, legacy orphaned leases and PHP fatal errors. |
| 51 |
Nginx/Caddy additionally test a real PHP-FPM `request_terminate_timeout`. |
| 52 |
OpenLiteSpeed additionally removes/restores the scoped `.htaccess` rule and checks |
| 53 |
the **actual** LSAPI `noabort` flag; it is not simulated. Manual worker requests |
| 54 |
include the same action query string as production dispatch, because the rule |
| 55 |
is intentionally scoped to that query string. |
| 56 |
|
| 57 |
For fast reproducible stale checks, the control fixture changes `started_at` to |
| 58 |
121 seconds ago **after** a real worker has started or died. The production |
| 59 |
120-second threshold is unchanged. A live worker must still suppress the alert |
| 60 |
while it holds the real DB lock. The batch window is one second in this fixture; |
| 61 |
the production default remains twenty seconds. |
| 62 |
|
| 63 |
Each recovery start records its PHP PID and the queue's attempt counter. Recovery |
| 64 |
requires distinct consecutive attempts and exactly one returned execution. This |
| 65 |
checks normal retries and catches duplicate execution within an attempt. |
| 66 |
|
| 67 |
`results.json` records scenarios, assertions, actual PHP SAPI/version and sample |
| 68 |
health states. `containers.log` retains HTTP/FPM logs and `images.json` records |
| 69 |
image digests. Failed runs retain the last control state for diagnosis. The |
| 70 |
control token is never written to the reports. |
| 71 |
|
| 72 |
Official configuration references: |
| 73 |
|
| 74 |
- [](https://docs.litespeedtech.com/cloud/docker/openlitespeed/LiteSpeed's Docker image](https://docs.litespeedtech.com/cloud/docker/openlitespeed/](https://docs.litespeedtech.com/cloud/docker/openlitespeed/) |
| 75 |
- [](https://docs.litespeedtech.com/lsws/extapp/php/configuration/control/LiteSpeed connection abort protection](https://docs.litespeedtech.com/lsws/extapp/php/configuration/control/](https://docs.litespeedtech.com/lsws/extapp/php/configuration/control/) |
| 76 |
- [](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.htmlNginx FastCGI handling](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html) |
| 77 |
- [](https://caddyserver.com/docs/caddyfile/directives/php_fastcgiCaddy PHP FastCGI handling](https://caddyserver.com/docs/caddyfile/directives/php_fastcgi](https://caddyserver.com/docs/caddyfile/directives/php_fastcgi) |
| 78 |
|