Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
RuntimeException
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
7 / 7
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forUnsupportedForking
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forUnableToForkWorker
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forWorkerWaitFailure
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forUndetectableProcessIdentifier
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forWorkerOutputAllocationFailure
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forWorkersWaitFailure
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5/**
6 * This file is part of fast-forward/fork.
7 *
8 * This source file is subject to the license bundled
9 * with this source code in the file LICENSE.
10 *
11 * @copyright Copyright (c) 2026 Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
12 * @license   https://opensource.org/licenses/MIT MIT License
13 *
14 * @see       https://github.com/php-fast-forward/fork
15 * @see       https://github.com/php-fast-forward
16 * @see       https://datatracker.ietf.org/doc/html/rfc2119
17 */
18
19namespace FastForward\Fork\Exception;
20
21/**
22 * Represents runtime failures raised while spawning, coordinating, or monitoring
23 * worker processes.
24 *
25 * This exception type is intended for operational failures that occur during
26 * process management, transport allocation, PID resolution, or wait handling.
27 * Callers MUST treat this exception as an execution-time failure rather than as
28 * an indication of invalid API usage. Library internals SHOULD use this
29 * exception when an operation is valid in principle but cannot be completed in
30 * the current runtime state.
31 */
32 class RuntimeException extends \RuntimeException implements ForkExceptionInterface
33{
34    /**
35     * Initializes the exception with a descriptive message.
36     *
37     * This constructor is private to enforce the use of named constructors for specific
38     * logic violation scenarios, ensuring that each exception instance is created with
39     * a clear and relevant message.
40     *
41     * @param string $message
42     */
43    private function __construct(string $message)
44    {
45        parent::__construct($message);
46    }
47
48    /**
49     * Creates an exception for runtimes that cannot support process forking.
50     *
51     * The current runtime MUST provide the capabilities required for safe worker
52     * process creation. If those capabilities are unavailable, the library SHALL
53     * reject the operation by raising this exception.
54     *
55     * @return self a new instance describing the unsupported runtime
56     */
57    public static function forUnsupportedForking(): self
58    {
59        return new self('Process forking is not supported in the current runtime.');
60    }
61
62    /**
63     * Creates an exception for failed worker fork attempts.
64     *
65     * Worker creation MUST succeed before the library can continue process
66     * orchestration. If the underlying fork operation fails, this exception MUST
67     * be thrown to indicate that no valid worker process could be established.
68     *
69     * @return self a new instance describing the fork failure
70     */
71    public static function forUnableToForkWorker(): self
72    {
73        return new self('Unable to fork a new worker process.');
74    }
75
76    /**
77     * Creates an exception for failures while waiting on a specific worker.
78     *
79     * Waiting on an individual worker SHOULD complete successfully when the
80     * worker is under manager control. If the wait operation fails, the library
81     * SHALL raise this exception with contextual error information.
82     *
83     * @param int $workerPid the process identifier of the worker that could not
84     *                       be awaited successfully
85     * @param string $error the low-level error message associated with the wait
86     *                      failure
87     *
88     * @return self a new instance describing the worker wait failure
89     */
90    public static function forWorkerWaitFailure(int $workerPid, string $error): self
91    {
92        return new self(\sprintf('Unable to wait for worker %d: %s', $workerPid, $error));
93    }
94
95    /**
96     * Creates an exception for failures while resolving the current PID.
97     *
98     * The library MUST be able to determine the current process identifier to
99     * distinguish master and worker execution contexts correctly. If PID
100     * detection fails, continued execution SHALL NOT be considered reliable.
101     *
102     * @return self a new instance describing the PID detection failure
103     */
104    public static function forUndetectableProcessIdentifier(): self
105    {
106        return new self('Unable to detect the current process identifier.');
107    }
108
109    /**
110     * Creates an exception for failures while allocating worker output transport.
111     *
112     * Worker output transport resources MUST be allocated before output can be
113     * captured or monitored safely. If transport allocation fails, this
114     * exception SHALL indicate that the worker communication channel could not be
115     * prepared.
116     *
117     * @return self a new instance describing the output transport allocation failure
118     */
119    public static function forWorkerOutputAllocationFailure(): self
120    {
121        return new self('Unable to allocate transport for worker output.');
122    }
123
124    /**
125     * Creates an exception for failures while waiting on multiple workers.
126     *
127     * Group wait operations SHOULD reconcile all targeted workers in a
128     * predictable manner. If the aggregate wait operation fails, this exception
129     * MUST communicate the underlying error so the caller can handle the runtime
130     * failure explicitly.
131     *
132     * @param string $error the low-level error message associated with the group
133     *                      wait failure
134     *
135     * @return self a new instance describing the multi-worker wait failure
136     */
137    public static function forWorkersWaitFailure(string $error): self
138    {
139        return new self(\sprintf('Unable to wait for workers: %s', $error));
140    }
141}