Skip to content

Commit 8751001

Browse files
authored
Merge branch 'main' into nicer-app-emails
2 parents a42c799 + 89b1d8b commit 8751001

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+5725
-1433
lines changed

apps/supervisor/src/env.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,16 @@ const Env = z.object({
3535
TRIGGER_DEQUEUE_ENABLED: BoolEnv.default(true),
3636
TRIGGER_DEQUEUE_INTERVAL_MS: z.coerce.number().int().default(250),
3737
TRIGGER_DEQUEUE_IDLE_INTERVAL_MS: z.coerce.number().int().default(1000),
38-
TRIGGER_DEQUEUE_MAX_RUN_COUNT: z.coerce.number().int().default(10),
39-
TRIGGER_DEQUEUE_MAX_CONSUMER_COUNT: z.coerce.number().int().default(1),
38+
TRIGGER_DEQUEUE_MAX_RUN_COUNT: z.coerce.number().int().default(1),
39+
TRIGGER_DEQUEUE_MIN_CONSUMER_COUNT: z.coerce.number().int().default(1),
40+
TRIGGER_DEQUEUE_MAX_CONSUMER_COUNT: z.coerce.number().int().default(10),
41+
TRIGGER_DEQUEUE_SCALING_STRATEGY: z.enum(["none", "smooth", "aggressive"]).default("none"),
42+
TRIGGER_DEQUEUE_SCALING_UP_COOLDOWN_MS: z.coerce.number().int().default(5000), // 5 seconds
43+
TRIGGER_DEQUEUE_SCALING_DOWN_COOLDOWN_MS: z.coerce.number().int().default(30000), // 30 seconds
44+
TRIGGER_DEQUEUE_SCALING_TARGET_RATIO: z.coerce.number().default(1.0), // Target ratio of queue items to consumers (1.0 = 1 item per consumer)
45+
TRIGGER_DEQUEUE_SCALING_EWMA_ALPHA: z.coerce.number().min(0).max(1).default(0.3), // Smooths queue length measurements (0=historical, 1=current)
46+
TRIGGER_DEQUEUE_SCALING_BATCH_WINDOW_MS: z.coerce.number().int().positive().default(1000), // Batch window for metrics processing (ms)
47+
TRIGGER_DEQUEUE_SCALING_DAMPING_FACTOR: z.coerce.number().min(0).max(1).default(0.7), // Smooths consumer count changes after EWMA (0=no scaling, 1=immediate)
4048

4149
// Optional services
4250
TRIGGER_WARM_START_URL: z.string().optional(),
@@ -77,6 +85,10 @@ const Env = z.object({
7785
KUBERNETES_EPHEMERAL_STORAGE_SIZE_LIMIT: z.string().default("10Gi"),
7886
KUBERNETES_EPHEMERAL_STORAGE_SIZE_REQUEST: z.string().default("2Gi"),
7987
KUBERNETES_STRIP_IMAGE_DIGEST: BoolEnv.default(false),
88+
KUBERNETES_CPU_REQUEST_MIN_CORES: z.coerce.number().min(0).default(0),
89+
KUBERNETES_CPU_REQUEST_RATIO: z.coerce.number().min(0).max(1).default(0.75), // Ratio of CPU limit, so 0.75 = 75% of CPU limit
90+
KUBERNETES_MEMORY_REQUEST_MIN_GB: z.coerce.number().min(0).default(0),
91+
KUBERNETES_MEMORY_REQUEST_RATIO: z.coerce.number().min(0).max(1).default(1), // Ratio of memory limit, so 1 = 100% of memory limit
8092

8193
// Placement tags settings
8294
PLACEMENT_TAGS_ENABLED: BoolEnv.default(false),

apps/supervisor/src/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,18 @@ class ManagedSupervisor {
128128
dequeueIdleIntervalMs: env.TRIGGER_DEQUEUE_IDLE_INTERVAL_MS,
129129
queueConsumerEnabled: env.TRIGGER_DEQUEUE_ENABLED,
130130
maxRunCount: env.TRIGGER_DEQUEUE_MAX_RUN_COUNT,
131-
maxConsumerCount: env.TRIGGER_DEQUEUE_MAX_CONSUMER_COUNT,
131+
metricsRegistry: register,
132+
scaling: {
133+
strategy: env.TRIGGER_DEQUEUE_SCALING_STRATEGY,
134+
minConsumerCount: env.TRIGGER_DEQUEUE_MIN_CONSUMER_COUNT,
135+
maxConsumerCount: env.TRIGGER_DEQUEUE_MAX_CONSUMER_COUNT,
136+
scaleUpCooldownMs: env.TRIGGER_DEQUEUE_SCALING_UP_COOLDOWN_MS,
137+
scaleDownCooldownMs: env.TRIGGER_DEQUEUE_SCALING_DOWN_COOLDOWN_MS,
138+
targetRatio: env.TRIGGER_DEQUEUE_SCALING_TARGET_RATIO,
139+
ewmaAlpha: env.TRIGGER_DEQUEUE_SCALING_EWMA_ALPHA,
140+
batchWindowMs: env.TRIGGER_DEQUEUE_SCALING_BATCH_WINDOW_MS,
141+
dampingFactor: env.TRIGGER_DEQUEUE_SCALING_DAMPING_FACTOR,
142+
},
132143
runNotificationsEnabled: env.TRIGGER_WORKLOAD_API_ENABLED,
133144
heartbeatIntervalSeconds: env.TRIGGER_WORKER_HEARTBEAT_INTERVAL_SECONDS,
134145
sendRunDebugLogs: env.SEND_RUN_DEBUG_LOGS,

apps/supervisor/src/workloadManager/kubernetes.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ export class KubernetesWorkloadManager implements WorkloadManager {
2020
private namespace = env.KUBERNETES_NAMESPACE;
2121
private placementTagProcessor: PlacementTagProcessor;
2222

23+
// Resource settings
24+
private readonly cpuRequestMinCores = env.KUBERNETES_CPU_REQUEST_MIN_CORES;
25+
private readonly cpuRequestRatio = env.KUBERNETES_CPU_REQUEST_RATIO;
26+
private readonly memoryRequestMinGb = env.KUBERNETES_MEMORY_REQUEST_MIN_GB;
27+
private readonly memoryRequestRatio = env.KUBERNETES_MEMORY_REQUEST_RATIO;
28+
2329
constructor(private opts: WorkloadManagerOptions) {
2430
this.k8s = createK8sApi();
2531
this.placementTagProcessor = new PlacementTagProcessor({
@@ -63,6 +69,10 @@ export class KubernetesWorkloadManager implements WorkloadManager {
6369
return imageRef.substring(0, atIndex);
6470
}
6571

72+
private clamp(value: number, min: number, max: number): number {
73+
return Math.min(Math.max(value, min), max);
74+
}
75+
6676
async create(opts: WorkloadManagerCreateOptions) {
6777
this.logger.log("[KubernetesWorkloadManager] Creating container", { opts });
6878

@@ -295,9 +305,16 @@ export class KubernetesWorkloadManager implements WorkloadManager {
295305
}
296306

297307
#getResourceRequestsForMachine(preset: MachinePreset): ResourceQuantities {
308+
const cpuRequest = preset.cpu * this.cpuRequestRatio;
309+
const memoryRequest = preset.memory * this.memoryRequestRatio;
310+
311+
// Clamp between min and max
312+
const clampedCpu = this.clamp(cpuRequest, this.cpuRequestMinCores, preset.cpu);
313+
const clampedMemory = this.clamp(memoryRequest, this.memoryRequestMinGb, preset.memory);
314+
298315
return {
299-
cpu: `${preset.cpu * 0.75}`,
300-
memory: `${preset.memory}G`,
316+
cpu: `${clampedCpu}`,
317+
memory: `${clampedMemory}G`,
301318
};
302319
}
303320

0 commit comments

Comments
 (0)