healthz: depend on Publisher to force bundle deep-load (perfsmoke gap)
v0.1.0 shipped two bugs that left /healthz returning 200 against a
half-loaded bundle: the path-repo symlink dangling at runtime in the
AppImage (vendor/php-qml/bridge → nonexistent), and the writable
cache-dir bug (Symfony couldn't create var/cache/prod). HealthController
returned a static {status:"ok"} without ever touching any BridgeBundle
service, so perfsmoke + the connection-state probe both passed even
when the bundle's autoload was broken — first sign of trouble was a
500 from /api/todos under real load.
Inject Publisher (the bundle's Mercure-publish wrapper) via constructor
and reference its FQN in the response body. Two effects:
- Symfony's container resolves Publisher when the controller is
instantiated; if the bundle's autoload is broken, the controller
can't even construct, /healthz returns 500.
- The response now includes `bundle: "PhpQml\Bridge\Publisher"` —
proves to perfsmoke + dev console that the canary is live, not a
cached static response.
Connection-state probe semantics unchanged: still 200 = Online,
non-200 = Reconnecting/Offline. Probe interval is 5s — Publisher's
construction is constant-time, no perf concern.
No new public API: /healthz response gained a `bundle` field
(additive, JSON parsers ignore unknown keys); 200 vs 500 boundary is
preserved. No existing consumer broken.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,18 +4,33 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpQml\Bridge\Controller;
|
||||
|
||||
use PhpQml\Bridge\Publisher;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
/**
|
||||
* Readiness probe used by the Qt host to detect when the backend is up.
|
||||
* See PLAN.md §3 (*Startup*, step 4).
|
||||
*
|
||||
* Publisher is injected purely as a deep-health canary: if the bridge
|
||||
* bundle's autoload or container wiring is broken (e.g. a packaging build
|
||||
* with a dangling vendor path-repo symlink), this controller can't even
|
||||
* be constructed, so /healthz fails 500 instead of misleadingly returning
|
||||
* 200 against a half-loaded bundle.
|
||||
*/
|
||||
final class HealthController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Publisher $publisher,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/healthz', name: 'php_qml_bridge_healthz', methods: ['GET'])]
|
||||
public function __invoke(): JsonResponse
|
||||
{
|
||||
return new JsonResponse(['status' => 'ok']);
|
||||
return new JsonResponse([
|
||||
'status' => 'ok',
|
||||
'bundle' => $this->publisher::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user