@@ -118,6 +118,30 @@ application deadline if you need to poll for the final result. Never automatical |
118 | 118 | retry a command with side effects after an ambiguous disconnect. |
119 | 119 | </Warning> |
120 | 120 |
|
| 121 | +## Worker locks and retries |
| 122 | + |
| 123 | +Your application owns its queue, lock leases and execution records. Docker PHP |
| 124 | +provides the polling and stdin APIs; it does not acquire Redis locks, acknowledge |
| 125 | +jobs or deduplicate executions. |
| 126 | + |
| 127 | +Acquire the lease and persist the application execution ID and Docker exec ID |
| 128 | +before starting the command. Renew the lease between polls, atomically comparing |
| 129 | +its unique owner token so an expired worker cannot renew another worker's lock. |
| 130 | +Use the ten-second heartbeat hook above even when the command is silent. |
| 131 | +Choose a lease duration with enough margin for synchronous setup/status requests |
| 132 | +and delayed heartbeats; a ten-second schedule is not a guarantee of exact timing. |
| 133 | + |
| 134 | +If renewal fails, stop sending input and close the local session. A heartbeat |
| 135 | +exception passed through `wait($tick)` does this automatically. Record the failed |
| 136 | +or uncertain attempt before acknowledging its job, and retain the Docker exec ID |
| 137 | +for later inspection. A failed worker result does not prove the command stopped |
| 138 | +or that it had no side effects. |
| 139 | + |
| 140 | +Use persisted execution state to deduplicate repeated job deliveries. Before |
| 141 | +starting another attempt after a lost lease or disconnect, confirm the previous |
| 142 | +command has stopped and reconcile any side effects. A new queue delivery or an |
| 143 | +expired lock alone does not make another exec safe. |
| 144 | + |
121 | 145 | ## Transports and TTY |
122 | 146 |
|
123 | 147 | This feature supports the bundled Unix, TCP and TLS socket transport. Guzzle and |
@@ -129,3 +153,33 @@ terminal semantics, not separate stdout/stderr pipes. `closeStdin()` deliberatel |
129 | 153 | rejects TTY sessions: Docker can close their output when socket stdin reaches EOF. |
130 | 154 | Use terminal input or let the command exit; use `Tty=false` for JSON-input managers. |
131 | 155 | The `Tty` setting must match at exec creation and start. |
| 156 | + |
| 157 | +## Maintainer validation |
| 158 | + |
| 159 | +On 6 October 2026, a private application canary tested |
| 160 | +[client revision `fbdb2cc`](https://github.com/docker-php/docker-php/commit/fbdb2cc2432b1ba9341f144a2f551523536e4a4c) |
| 161 | +with API package `7.1.45.0` against Docker Engine `29.8.1`, using API `1.45`. |
| 162 | +Its worker sent fixed JSON stdin, closed stdin and polled a command that produced |
| 163 | +no output for 40 seconds. |
| 164 | + |
| 165 | +| Application check | Observed result | |
| 166 | +| --- | --- | |
| 167 | +| Silent execution | Four Redis lease renewals; completed result callback delivered; queue job acknowledged. | |
| 168 | +| Lease loss after the first renewal | The next renewal failed and the failed result callback was delivered. The disconnected container command later completed. | |
| 169 | +| Identical admission and job replay after either result | One manager start per execution, one attempt and no second command. | |
| 170 | + |
| 171 | +The locks, result callbacks and replay guards in these checks belonged to the |
| 172 | +application. Concurrent workers, HTTP submission retries and network-failure |
| 173 | +recovery still need separate tests. |
| 174 | + |
| 175 | +The library's stream and local transport-fixture tests cover partial stdin |
| 176 | +writes, backpressure, EOF, idle ticks, deadline expiry, callback failures and |
| 177 | +Unix/TCP/TLS connections. Run them without a Docker daemon: |
| 178 | + |
| 179 | +```bash |
| 180 | +vendor/bin/phpunit --filter 'InteractiveExec(Stream|Transport)Test' --disallow-test-output |
| 181 | +``` |
| 182 | + |
| 183 | +`tests/Resource/InteractiveExecResourceTest.php` also exercises stdin, TTY output, |
| 184 | +exit codes and container-side timeouts against a development Docker daemon. |
| 185 | +Those resource tests create and remove their own containers. |