()
| 79 | } |
| 80 | |
| 81 | export async function scaleCommand() { |
| 82 | const dir = findInstallDir() |
| 83 | const config = readConfig(dir) |
| 84 | if (!config) { |
| 85 | p.log.error('No LearnHouse installation found. Run setup first.') |
| 86 | process.exit(1) |
| 87 | } |
| 88 | |
| 89 | p.intro(pc.cyan('LearnHouse Resource Limits')) |
| 90 | |
| 91 | // Show current usage |
| 92 | p.log.step('Current Resource Usage') |
| 93 | try { |
| 94 | const stats = dockerStats(config.installDir) |
| 95 | p.log.message(pc.dim(stats.trim())) |
| 96 | } catch { |
| 97 | try { |
| 98 | const id = config.deploymentId || autoDetectDeploymentId() |
| 99 | const running = listDeploymentContainers(id || undefined) |
| 100 | .filter((c) => c.status.toLowerCase().startsWith('up')) |
| 101 | .map((c) => c.name) |
| 102 | if (running.length > 0) { |
| 103 | const stats = dockerStatsForContainers(running) |
| 104 | p.log.message(pc.dim(stats.trim())) |
| 105 | } else { |
| 106 | p.log.warn('No running containers found.') |
| 107 | } |
| 108 | } catch { |
| 109 | p.log.warn('Could not retrieve current stats. Services may not be running.') |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | const composePath = path.join(config.installDir, 'docker-compose.yml') |
| 114 | if (!fs.existsSync(composePath)) { |
| 115 | p.log.error('docker-compose.yml not found.') |
| 116 | process.exit(1) |
| 117 | } |
| 118 | |
| 119 | let composeContent = fs.readFileSync(composePath, 'utf-8') |
| 120 | const currentLimits = parseMemLimit(composePath) |
| 121 | |
| 122 | // Prompt for each service |
| 123 | p.log.step('Set Memory Limits') |
| 124 | p.log.info(pc.dim('Examples: 256m, 512m, 1g, 2g (leave empty to skip)')) |
| 125 | |
| 126 | let changed = false |
| 127 | |
| 128 | for (const service of SERVICES) { |
| 129 | const current = currentLimits.get(service) |
| 130 | const label = current |
| 131 | ? `Memory limit for ${pc.bold(service)} (current: ${current})` |
| 132 | : `Memory limit for ${pc.bold(service)} (not set)` |
| 133 | |
| 134 | const value = await p.text({ |
| 135 | message: label, |
| 136 | placeholder: current ? undefined : 'e.g. 512m', |
| 137 | defaultValue: current || '', |
| 138 | }) |
no test coverage detected