|
|
@@ -74,6 +74,7 @@ export const serviceValidator = z.object({
|
|
|
port: serviceNumberValidator,
|
|
|
cpuCores: serviceNumberValidator,
|
|
|
ramMegabytes: serviceNumberValidator,
|
|
|
+ gpuCoresNvidia: serviceNumberValidator,
|
|
|
smartOptimization: serviceBooleanValidator.optional(),
|
|
|
config: z.discriminatedUnion("type", [
|
|
|
webConfigValidator,
|
|
|
@@ -107,31 +108,32 @@ export type SerializedService = {
|
|
|
cpuCores: number;
|
|
|
ramMegabytes: number;
|
|
|
smartOptimization?: boolean;
|
|
|
+ gpuCoresNvidia: number;
|
|
|
config:
|
|
|
- | {
|
|
|
- type: "web";
|
|
|
- domains: {
|
|
|
- name: string;
|
|
|
- }[];
|
|
|
- autoscaling?: SerializedAutoscaling;
|
|
|
- healthCheck?: SerializedHealthcheck;
|
|
|
- private?: boolean;
|
|
|
- ingressAnnotations: Record<string, string>;
|
|
|
- }
|
|
|
- | {
|
|
|
- type: "worker";
|
|
|
- autoscaling?: SerializedAutoscaling;
|
|
|
- }
|
|
|
- | {
|
|
|
- type: "job";
|
|
|
- allowConcurrent?: boolean;
|
|
|
- cron: string;
|
|
|
- suspendCron?: boolean;
|
|
|
- timeoutSeconds: number;
|
|
|
- }
|
|
|
- | {
|
|
|
- type: "predeploy";
|
|
|
- };
|
|
|
+ | {
|
|
|
+ type: "web";
|
|
|
+ domains: {
|
|
|
+ name: string;
|
|
|
+ }[];
|
|
|
+ autoscaling?: SerializedAutoscaling;
|
|
|
+ healthCheck?: SerializedHealthcheck;
|
|
|
+ private?: boolean;
|
|
|
+ ingressAnnotations: Record<string, string>;
|
|
|
+ }
|
|
|
+ | {
|
|
|
+ type: "worker";
|
|
|
+ autoscaling?: SerializedAutoscaling;
|
|
|
+ }
|
|
|
+ | {
|
|
|
+ type: "job";
|
|
|
+ allowConcurrent?: boolean;
|
|
|
+ cron: string;
|
|
|
+ suspendCron?: boolean;
|
|
|
+ timeoutSeconds: number;
|
|
|
+ }
|
|
|
+ | {
|
|
|
+ type: "predeploy";
|
|
|
+ };
|
|
|
};
|
|
|
|
|
|
export function isPredeployService(service: SerializedService | ClientService) {
|
|
|
@@ -181,6 +183,7 @@ export function defaultSerialized({
|
|
|
port: 3000,
|
|
|
cpuCores: defaultCPU,
|
|
|
ramMegabytes: defaultRAM,
|
|
|
+ gpuCoresNvidia: 0,
|
|
|
smartOptimization: true,
|
|
|
};
|
|
|
|
|
|
@@ -247,6 +250,7 @@ export function serializeService(service: ClientService): SerializedService {
|
|
|
cpuCores: service.cpuCores.value,
|
|
|
ramMegabytes: Math.round(service.ramMegabytes.value), // RAM must be an integer
|
|
|
smartOptimization: service.smartOptimization?.value,
|
|
|
+ gpuCoresNvidia: service.gpuCoresNvidia.value,
|
|
|
config: match(service.config)
|
|
|
.with({ type: "web" }, (config) =>
|
|
|
Object.freeze({
|
|
|
@@ -313,6 +317,7 @@ export function deserializeService({
|
|
|
instances: ServiceField.number(service.instances, override?.instances),
|
|
|
port: ServiceField.number(service.port, override?.port),
|
|
|
cpuCores: ServiceField.number(service.cpuCores, override?.cpuCores),
|
|
|
+ gpuCoresNvidia: ServiceField.number(service.gpuCoresNvidia, override?.gpuCoresNvidia),
|
|
|
ramMegabytes: ServiceField.number(
|
|
|
service.ramMegabytes,
|
|
|
override?.ramMegabytes
|
|
|
@@ -385,11 +390,11 @@ export function deserializeService({
|
|
|
ingressAnnotations: uniqueAnnotations,
|
|
|
private:
|
|
|
typeof config.private === "boolean" ||
|
|
|
- typeof overrideWebConfig?.private === "boolean"
|
|
|
+ typeof overrideWebConfig?.private === "boolean"
|
|
|
? ServiceField.boolean(config.private, overrideWebConfig?.private)
|
|
|
: setDefaults
|
|
|
- ? ServiceField.boolean(false, undefined)
|
|
|
- : undefined,
|
|
|
+ ? ServiceField.boolean(false, undefined)
|
|
|
+ : undefined,
|
|
|
},
|
|
|
};
|
|
|
})
|
|
|
@@ -419,34 +424,34 @@ export function deserializeService({
|
|
|
type: "job" as const,
|
|
|
allowConcurrent:
|
|
|
typeof config.allowConcurrent === "boolean" ||
|
|
|
- typeof overrideJobConfig?.allowConcurrent === "boolean"
|
|
|
+ typeof overrideJobConfig?.allowConcurrent === "boolean"
|
|
|
? ServiceField.boolean(
|
|
|
- config.allowConcurrent,
|
|
|
- overrideJobConfig?.allowConcurrent
|
|
|
- )
|
|
|
+ config.allowConcurrent,
|
|
|
+ overrideJobConfig?.allowConcurrent
|
|
|
+ )
|
|
|
: setDefaults
|
|
|
- ? ServiceField.boolean(false, undefined)
|
|
|
- : undefined,
|
|
|
+ ? ServiceField.boolean(false, undefined)
|
|
|
+ : undefined,
|
|
|
cron: ServiceField.string(config.cron, overrideJobConfig?.cron),
|
|
|
suspendCron:
|
|
|
typeof config.suspendCron === "boolean" ||
|
|
|
- typeof overrideJobConfig?.suspendCron === "boolean"
|
|
|
+ typeof overrideJobConfig?.suspendCron === "boolean"
|
|
|
? ServiceField.boolean(
|
|
|
- config.suspendCron,
|
|
|
- overrideJobConfig?.suspendCron
|
|
|
- )
|
|
|
+ config.suspendCron,
|
|
|
+ overrideJobConfig?.suspendCron
|
|
|
+ )
|
|
|
: setDefaults
|
|
|
- ? ServiceField.boolean(false, undefined)
|
|
|
- : undefined,
|
|
|
+ ? ServiceField.boolean(false, undefined)
|
|
|
+ : undefined,
|
|
|
timeoutSeconds:
|
|
|
config.timeoutSeconds != 0
|
|
|
? ServiceField.number(
|
|
|
- config.timeoutSeconds,
|
|
|
- overrideJobConfig?.timeoutSeconds
|
|
|
- )
|
|
|
+ config.timeoutSeconds,
|
|
|
+ overrideJobConfig?.timeoutSeconds
|
|
|
+ )
|
|
|
: setDefaults
|
|
|
- ? ServiceField.number(3600, overrideJobConfig?.timeoutSeconds)
|
|
|
- : ServiceField.number(0, overrideJobConfig?.timeoutSeconds),
|
|
|
+ ? ServiceField.number(3600, overrideJobConfig?.timeoutSeconds)
|
|
|
+ : ServiceField.number(0, overrideJobConfig?.timeoutSeconds),
|
|
|
},
|
|
|
};
|
|
|
})
|
|
|
@@ -573,22 +578,22 @@ export function serializedServiceFromProto({
|
|
|
.with({ case: "jobConfig" }, ({ value }) =>
|
|
|
isPredeploy
|
|
|
? {
|
|
|
- ...service,
|
|
|
- run: service.runOptional ?? service.run,
|
|
|
- config: {
|
|
|
- type: "predeploy" as const,
|
|
|
- },
|
|
|
- }
|
|
|
+ ...service,
|
|
|
+ run: service.runOptional ?? service.run,
|
|
|
+ config: {
|
|
|
+ type: "predeploy" as const,
|
|
|
+ },
|
|
|
+ }
|
|
|
: {
|
|
|
- ...service,
|
|
|
- run: service.runOptional ?? service.run,
|
|
|
- config: {
|
|
|
- type: "job" as const,
|
|
|
- ...value,
|
|
|
- allowConcurrent: value.allowConcurrentOptional,
|
|
|
- timeoutSeconds: Number(value.timeoutSeconds),
|
|
|
- },
|
|
|
- }
|
|
|
+ ...service,
|
|
|
+ run: service.runOptional ?? service.run,
|
|
|
+ config: {
|
|
|
+ type: "job" as const,
|
|
|
+ ...value,
|
|
|
+ allowConcurrent: value.allowConcurrentOptional,
|
|
|
+ timeoutSeconds: Number(value.timeoutSeconds),
|
|
|
+ },
|
|
|
+ }
|
|
|
)
|
|
|
.exhaustive();
|
|
|
}
|