mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-20 15:22:59 +00:00
fix(mesh): surface data-plane failures in health, meta, and Routing tab (#1088)
The three previously-silent console.warn paths in MeshService.setupMeshNetwork now route through a typed recordSetupFailure helper that classifies the failure (subnet_invalid, subnet_overlap, subnet_mismatch, ip_in_use, attach_failed, not_in_docker), emits a mesh.disable activity entry at the matching level (error for real failures, warn for the expected dev-mode not_in_docker case), and strips mesh_proxy_callback_bootstrap from advertised capabilities via CapabilityRegistry. /api/health gains a mesh.dataPlane block carrying the typed status. /api/mesh/status carries localDataPlane at the top level so the Routing tab renders a red banner with an operator-actionable recovery hint (set SENCHO_MESH_SUBNET to a free /24 and recreate the container) when the data plane is down. The success path re-enables the capability and flips the status to ok. Generalizes the previously-documented F-0 failure mode (IP-in-subnet collision) to also cover the subnet-pool-overlap case where another Docker bridge on the host already owns the requested CIDR.
This commit is contained in:
@@ -16,8 +16,9 @@ function actorFor(req: Request): string {
|
||||
meshRouter.get('/status', async (_req: Request, res: Response): Promise<void> => {
|
||||
if (!requireAdmiral(_req, res)) return;
|
||||
try {
|
||||
const status = await MeshService.getInstance().getStatus();
|
||||
res.json({ nodes: status });
|
||||
const mesh = MeshService.getInstance();
|
||||
const status = await mesh.getStatus();
|
||||
res.json({ nodes: status, localDataPlane: mesh.getDataPlaneStatus() });
|
||||
} catch (err) {
|
||||
console.warn('[mesh] /status failed:', sanitizeForLog((err as Error).message));
|
||||
res.status(500).json({ error: 'Failed to load mesh status' });
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Router, type Request, type Response } from 'express';
|
||||
import { getActiveCapabilities, getSenchoVersion } from '../services/CapabilityRegistry';
|
||||
import { MeshService } from '../services/MeshService';
|
||||
import SelfUpdateService from '../services/SelfUpdateService';
|
||||
|
||||
// Captured at boot. Exposed via /api/health and /api/meta so the Fleet update
|
||||
@@ -9,8 +10,19 @@ const processStartedAt = Date.now();
|
||||
export const metaRouter = Router();
|
||||
|
||||
// Public health endpoint (no auth). Used by Docker HEALTHCHECK and uptime monitors.
|
||||
// The `mesh.dataPlane` block reports whether `MeshService.setupMeshNetwork`
|
||||
// completed successfully; an `ok: false` value means cross-node mesh routing
|
||||
// is disabled on this node and the operator should consult the activity log
|
||||
// or set `SENCHO_MESH_SUBNET` to a free /24 and restart the container.
|
||||
metaRouter.get('/health', (_req: Request, res: Response): void => {
|
||||
res.json({ status: 'ok', uptime: process.uptime(), startedAt: processStartedAt });
|
||||
res.json({
|
||||
status: 'ok',
|
||||
uptime: process.uptime(),
|
||||
startedAt: processStartedAt,
|
||||
mesh: {
|
||||
dataPlane: MeshService.getInstance().getDataPlaneStatus(),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Public meta endpoint. Returns this instance's version and supported
|
||||
|
||||
Reference in New Issue
Block a user