@datalayer/core
Version:
[](https://datalayer.io)
230 lines (229 loc) • 9.99 kB
JavaScript
/*
* Copyright (c) 2023-2025 Datalayer, Inc.
* Distributed under the terms of the Modified BSD License.
*/
/**
* Runtimes mixin for managing computational environments and runtime instances.
* @module client/mixins/RuntimesMixin
*/
import * as environments from '../../api/runtimes/environments';
import * as runtimes from '../../api/runtimes/runtimes';
import * as snapshots from '../../api/runtimes/snapshots';
import { EnvironmentDTO } from '../../models/EnvironmentDTO';
import { RuntimeDTO } from '../../models/RuntimeDTO';
import { RuntimeSnapshotDTO } from '../../models/RuntimeSnapshotDTO';
import { HealthCheck } from '../../models/HealthCheck';
/** Runtimes mixin providing computational environment and runtime management. */
export function RuntimesMixin(Base) {
return class extends Base {
// ========================================================================
// Helper Functions
// ========================================================================
_extractRuntimePodName(runtimePodNameOrInstance) {
return typeof runtimePodNameOrInstance === 'string'
? runtimePodNameOrInstance
: runtimePodNameOrInstance.podName;
}
_extractSnapshotId(snapshotIdOrInstance) {
return typeof snapshotIdOrInstance === 'string'
? snapshotIdOrInstance
: snapshotIdOrInstance.uid;
}
// ========================================================================
// Environments
// ========================================================================
/**
* List all available computational environments.
* @returns Array of Environment model instances
*/
async listEnvironments() {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
const response = await environments.listEnvironments(token, runtimesRunUrl);
// Save for later use after first call
this.environments = response.environments.map(env => new EnvironmentDTO(env, this));
return this.environments;
}
// ========================================================================
// Runtimes
// ========================================================================
/**
* Create a new computational runtime.
* @param environmentName - Name of the environment to use
* @param type - Type of runtime
* @param givenName - User-friendly name for the runtime
* @param creditsLimit - Credits limit
* @returns Created runtime
*/
async createRuntime(environmentName, type, givenName, minutesLimit, fromSnapshotId) {
if (!this.environments) {
await this.listEnvironments();
}
if (this.environments) {
const env = this.environments.find((e) => e.name === environmentName);
if (!env) {
throw new Error(`Environment "${environmentName}" not found. Available environments: ${this.environments.map((e) => e.name).join(', ')}`);
}
else {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
const creditsLimit = this.calculateCreditsFromMinutes(minutesLimit, env.burningRate);
const data = {
environment_name: environmentName,
type,
given_name: givenName,
credits_limit: creditsLimit,
from: fromSnapshotId,
};
const response = await runtimes.createRuntime(token, data, runtimesRunUrl);
return new RuntimeDTO(response.runtime, this);
}
}
else {
throw new Error('Environments not loaded');
}
}
/**
* List all runtimes.
* @returns Array of runtimes
*/
async listRuntimes() {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
const response = await runtimes.listRuntimes(token, runtimesRunUrl);
return response.runtimes.map(r => new RuntimeDTO(r, this));
}
/**
* Get details for a specific runtime by pod name.
* @param podName - Runtime pod name
* @returns Runtime details
*/
async getRuntime(podName) {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
const runtimeData = await runtimes.getRuntime(token, podName, runtimesRunUrl);
return new RuntimeDTO(runtimeData, this);
}
/**
* Delete a runtime permanently.
* @param podName - Runtime pod name
*/
async deleteRuntime(podName) {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
await runtimes.deleteRuntime(token, podName, runtimesRunUrl);
}
/**
* Terminate all runtimes.
* Lists all runtimes and deletes them in parallel.
* @returns Array of results for each deletion (fulfilled or rejected)
*/
async terminateAllRuntimes() {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
// List all runtimes
const response = await runtimes.listRuntimes(token, runtimesRunUrl);
// Delete all runtimes in parallel
const deletePromises = response.runtimes.map(runtime => runtimes.deleteRuntime(token, runtime.pod_name, runtimesRunUrl));
return Promise.allSettled(deletePromises);
}
// ========================================================================
// Snapshots
// ========================================================================
/**
* Create a snapshot of a runtime.
* @param podName - Pod name of the runtime to snapshot
* @param name - Name for the snapshot
* @param description - Description of the snapshot
* @param stop - Whether to stop the runtime after creating snapshot (defaults to false)
* @returns Created snapshot
*/
async createSnapshot(podName, name, description, stop = false) {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
const data = {
pod_name: podName,
name,
description,
stop,
};
const response = await snapshots.createSnapshot(token, data, runtimesRunUrl);
return new RuntimeSnapshotDTO(response.snapshot, this);
}
/**
* List all runtime snapshots.
* @returns Array of snapshots
*/
async listSnapshots() {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
const response = await snapshots.listSnapshots(token, runtimesRunUrl);
return response.snapshots.map(s => new RuntimeSnapshotDTO(s, this));
}
/**
* Get details for a specific snapshot by ID.
* @param id - Snapshot ID
* @returns Snapshot details
*/
async getSnapshot(id) {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
const response = await snapshots.getSnapshot(token, id, runtimesRunUrl);
return new RuntimeSnapshotDTO(response.snapshot, this);
}
/**
* Delete a snapshot permanently.
* @param id - Snapshot ID
*/
async deleteSnapshot(id) {
const token = this.getToken();
const runtimesRunUrl = this.getRuntimesRunUrl();
await snapshots.deleteSnapshot(token, id, runtimesRunUrl);
}
// ========================================================================
// Service Health Checks
// ========================================================================
/**
* Check the health status of the Runtimes service.
* @returns Health check result with status and response time
*/
async checkRuntimesHealth() {
const startTime = Date.now();
const errors = [];
let status = 'unknown';
let healthy = false;
try {
// Test basic connectivity by listing environments (lightweight operation)
const environments = await this.listEnvironments();
const responseTime = Date.now() - startTime;
if (Array.isArray(environments)) {
healthy = true;
status = 'operational';
}
else {
status = 'degraded';
errors.push('Unexpected response format from environments endpoint');
}
return new HealthCheck({
healthy,
status,
responseTime,
errors,
timestamp: new Date(),
}, this);
}
catch (error) {
const responseTime = Date.now() - startTime;
status = 'down';
errors.push(`Service unreachable: ${error}`);
return new HealthCheck({
healthy: false,
status,
responseTime,
errors,
timestamp: new Date(),
}, this);
}
}
};
}