services: enforce min memory limit

This commit is contained in:
Girish Ramakrishnan
2026-03-05 21:21:19 +05:30
parent 74c73c695f
commit 99c55cb22f
2 changed files with 37 additions and 4 deletions

View File

@@ -119,6 +119,7 @@ async function startInfra(restoreOptions) {
// short-circuit for the restart case
if (_.isEqual(infra, existingInfra)) {
debug('startInfra: infra is uptodate at version %s', infra.version);
safe(services.applyServiceLimits(), { debug });
await onInfraReady(false /* !infraChanged */);
return;
}

View File

@@ -1691,6 +1691,40 @@ async function applyMemoryLimit(id) {
await docker.update(containerName, memoryLimit);
}
async function applyServiceLimits() {
const servicesConfig = await getConfig();
let changed = false;
for (const id of Object.keys(SERVICES)) {
const defaultLimit = SERVICES[id].defaultMemoryLimit;
if (!defaultLimit) continue;
if (servicesConfig[id]?.memoryLimit && servicesConfig[id].memoryLimit < defaultLimit) {
servicesConfig[id].memoryLimit = defaultLimit;
changed = true;
}
safe(applyMemoryLimit(id), { debug });
}
if (changed) await settings.setJson(settings.SERVICES_CONFIG_KEY, servicesConfig);
const allApps = await apps.list();
for (const app of allApps) {
if (!app.manifest.addons?.redis || !app.enableRedis) continue;
const redisConfig = app.servicesConfig['redis'];
const defaultLimit = APP_SERVICES['redis'].defaultMemoryLimit;
if (redisConfig?.memoryLimit && redisConfig.memoryLimit < defaultLimit) {
app.servicesConfig['redis'].memoryLimit = defaultLimit;
await apps.update(app.id, { servicesConfig: app.servicesConfig });
}
safe(applyMemoryLimit(`redis:${app.id}`), { debug });
}
}
async function startTurn(existingInfra) {
assert.strictEqual(typeof existingInfra, 'object');
@@ -1854,10 +1888,7 @@ async function startServices(existingInfra, progressCallback) {
await fn(existingInfra);
}
// we always start db containers with unlimited memory. we then scale them down per configuration
for (const id of [ 'mysql', 'postgresql', 'mongodb' ]) {
safe(applyMemoryLimit(id), { debug }); // no waiting. and it's ok if applying service configs fails
}
safe(applyServiceLimits(), { debug });
}
async function teardownOauth(app, options) {
@@ -2239,6 +2270,7 @@ export default {
stopAppServices,
startServices,
applyServiceLimits,
moveDataDir, // localstorage specific command