Unify URL resolution, add health checker sync, and make modules optional

- Add url-resolver.js with single resolveServiceUrl() used by all 5 consumers
  (probes, health routes, health checker auto-config)
- Health checker now does full sync (add/update/remove) instead of add-only,
  and re-syncs automatically after every services.json mutation
- docker-maintenance and log-digest are now optional imports with try/catch,
  preventing container crashes when these files are absent
- Add null guards in routes/logs.js for graceful 503 responses

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 23:01:20 -07:00
parent 70b818c2bd
commit 2815233e86
7 changed files with 145 additions and 106 deletions

View File

@@ -8,6 +8,7 @@ const { APP, REGEX, TIMEOUTS } = require('../constants');
const { validateServiceConfig, isValidPort } = require('../input-validator');
const { exists } = require('../fs-helpers');
const { paginate, parsePaginationParams } = require('../pagination');
const { resolveServiceUrl } = require('../url-resolver');
module.exports = function(ctx) {
const router = express.Router();
@@ -33,10 +34,7 @@ module.exports = function(ctx) {
}
function resolveProbeUrl(id, service) {
if (id === 'internet') return 'https://www.google.com';
if (service?.isExternal && service.externalUrl) return service.externalUrl;
if (service?.url) return service.url.startsWith('http') ? service.url : `https://${service.url}`;
return ctx.buildServiceUrl(id);
return resolveServiceUrl(id, service, ctx.siteConfig, ctx.buildServiceUrl);
}
function requestStatusCode(url, method) {
@@ -308,6 +306,7 @@ module.exports = function(ctx) {
return services;
});
ctx.resyncHealthChecker?.().catch(() => {});
res.json({ success: true, message: `Service "${name}" added to dashboard` });
} catch (error) {
ctx.log.error('deploy', 'Error adding service', { error: error.message });
@@ -339,6 +338,7 @@ module.exports = function(ctx) {
}
await ctx.servicesStateManager.write(services);
ctx.resyncHealthChecker?.().catch(() => {});
res.json({
success: true,
@@ -367,6 +367,7 @@ module.exports = function(ctx) {
return ctx.errorResponse(res, 404, `Service "${id}" not found`);
}
ctx.resyncHealthChecker?.().catch(() => {});
res.json({ success: true, message: `Service "${id}" removed from dashboard` });
}, 'services-delete'));
@@ -454,6 +455,7 @@ module.exports = function(ctx) {
});
}
ctx.resyncHealthChecker?.().catch(() => {});
res.json({
success: true,
message: `Service updated: ${oldSubdomain} -> ${newSubdomain}`,