Implement stack health diagnostics, timeout adjustments, and cleanup dependencies

This commit is contained in:
Jeppe Bundgaard
2026-04-22 15:00:12 +02:00
parent f4952f16e6
commit fd830deda9
7 changed files with 54 additions and 23 deletions
File diff suppressed because one or more lines are too long
@@ -3,16 +3,6 @@ FROM ${BASE_IMAGE}
WORKDIR /opt/truckwash-edge-agent
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
curl \
ca-certificates \
libcurl4-openssl-dev \
libsqlite3-dev; \
docker-php-ext-install curl sqlite3; \
rm -rf /var/lib/apt/lists/*
COPY agent.php /opt/truckwash-edge-agent/agent.php
ENTRYPOINT ["php", "/opt/truckwash-edge-agent/agent.php"]
@@ -3,15 +3,6 @@ FROM ${BASE_IMAGE}
WORKDIR /opt/truckwash-edge-agent
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
curl \
ca-certificates \
libcurl4-openssl-dev; \
docker-php-ext-install curl; \
rm -rf /var/lib/apt/lists/*
COPY lan-worker.php /opt/truckwash-edge-agent/lan-worker.php
CMD ["php", "-S", "0.0.0.0:8090", "/opt/truckwash-edge-agent/lan-worker.php"]
@@ -1,3 +1,5 @@
version: "2.4"
services:
lan-worker:
build:
@@ -8,6 +8,7 @@ COMPOSE_FILE="$INSTALL_DIR/docker-compose.gateway.yml"
RUNTIME_DIR="$INSTALL_DIR/runtime"
ROLLBACK_STATUS_PATH="$RUNTIME_DIR/rollback-status.json"
STAGED_UPDATE_PATH="$RUNTIME_DIR/staged-update.json"
STACK_HEALTHCHECK_TIMEOUT_SECONDS="${STACK_HEALTHCHECK_TIMEOUT_SECONDS:-120}"
log() {
printf '[gateway-launcher] %s\n' "$1"
@@ -28,6 +29,17 @@ compose_cmd() {
return 1
}
print_compose_diagnostics() {
log "docker ps --format '{{.Names}} {{.Status}}'"
docker ps --format '{{.Names}} {{.Status}}' || true
log "compose ps"
compose_cmd -f "$COMPOSE_FILE" ps || true
log "compose logs --tail=80"
compose_cmd -f "$COMPOSE_FILE" logs --tail=80 || true
}
config_value() {
local key="$1"
local fallback="${2:-}"
@@ -137,14 +149,30 @@ healthcheck_stack() {
curl -fsS http://127.0.0.1:8090/health >/dev/null
}
wait_for_stack_health() {
local timeout_seconds="${1:-$STACK_HEALTHCHECK_TIMEOUT_SECONDS}"
local elapsed=0
while [ "$elapsed" -lt "$timeout_seconds" ]; do
if healthcheck_stack; then
return 0
fi
sleep 2
elapsed=$((elapsed + 2))
done
return 1
}
reconcile_stack() {
ensure_dirs
log "Reconciling compose stack"
apply_stack
sleep 5
if ! healthcheck_stack; then
if ! wait_for_stack_health "$STACK_HEALTHCHECK_TIMEOUT_SECONDS"; then
log "Healthcheck failed after compose rollout; reverting to previous artifacts"
print_compose_diagnostics
rollback_stack
return 1
fi
@@ -10,7 +10,7 @@ WorkingDirectory=/opt/truckwash-edge-agent
ExecStart=/opt/truckwash-edge-agent/gateway-launcher.sh up
ExecReload=/opt/truckwash-edge-agent/gateway-launcher.sh reconcile
ExecStop=/opt/truckwash-edge-agent/gateway-launcher.sh down
TimeoutStartSec=300
TimeoutStartSec=900
[Install]
WantedBy=multi-user.target
@@ -4,8 +4,16 @@ it('builds the installer around the compose stack artifacts and management polli
$managerSource = file_get_contents(app_path('classes/edge_gateway_manager.php'));
$serviceSource = file_get_contents(app_path('resources/edge-gateway-agent/truckwash-edge-agent.service'));
$stackServiceSource = file_get_contents(app_path('resources/edge-gateway-agent/truckwash-edge-gateway-stack.service'));
$launcherSource = file_get_contents(app_path('resources/edge-gateway-agent/gateway-launcher.sh'));
$composeSource = file_get_contents(app_path('resources/edge-gateway-agent/docker-compose.gateway.yml'));
$edgeDockerfileSource = file_get_contents(app_path('resources/edge-gateway-agent/Dockerfile.edge-agent'));
$workerDockerfileSource = file_get_contents(app_path('resources/edge-gateway-agent/Dockerfile.lan-worker'));
expect($managerSource)->not->toBeFalse();
expect($launcherSource)->not->toBeFalse();
expect($composeSource)->not->toBeFalse();
expect($edgeDockerfileSource)->not->toBeFalse();
expect($workerDockerfileSource)->not->toBeFalse();
expect($managerSource)->toContain("'operationPollTimeoutSeconds' => self::COMMAND_POLL_TIMEOUT_SECONDS");
expect($managerSource)->toContain('fetch_http "Verify install token" "__VERIFY_URL__"');
expect($managerSource)->toContain('fetch_http "Download PHP edge agent" "__AGENT_URL__" "$INSTALL_DIR/agent.php"');
@@ -31,6 +39,18 @@ it('builds the installer around the compose stack artifacts and management polli
expect($managerSource)->not->toContain('"brokerUrl"');
expect($serviceSource)->toContain('ExecStart=/usr/bin/php /opt/truckwash-edge-agent/agent.php --config /opt/truckwash-edge-agent/config.json');
expect($stackServiceSource)->toContain('ExecStart=/opt/truckwash-edge-agent/gateway-launcher.sh up');
expect($stackServiceSource)->toContain('TimeoutStartSec=900');
expect($launcherSource)->toContain('STACK_HEALTHCHECK_TIMEOUT_SECONDS="${STACK_HEALTHCHECK_TIMEOUT_SECONDS:-120}"');
expect($launcherSource)->toContain('wait_for_stack_health');
expect($launcherSource)->toContain('compose_cmd -f "$COMPOSE_FILE" logs --tail=80 || true');
expect($composeSource)->toContain('version: "2.4"');
expect($composeSource)->toContain('condition: service_healthy');
expect($edgeDockerfileSource)->toContain('FROM ${BASE_IMAGE}');
expect($edgeDockerfileSource)->toContain('COPY agent.php /opt/truckwash-edge-agent/agent.php');
expect($edgeDockerfileSource)->not->toContain('docker-php-ext-install');
expect($workerDockerfileSource)->toContain('FROM ${BASE_IMAGE}');
expect($workerDockerfileSource)->toContain('COPY lan-worker.php /opt/truckwash-edge-agent/lan-worker.php');
expect($workerDockerfileSource)->not->toContain('docker-php-ext-install');
expect($serviceSource)->not->toContain('node /opt/truckwash-edge-agent/agent.mjs');
});