UNPKG

@cocalc/database

Version:

CoCalc: code for working with our PostgreSQL database

56 lines (52 loc) 2.05 kB
/* * This file is part of CoCalc: Copyright © 2020 Sagemath, Inc. * License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details */ import { delay } from "awaiting"; import { PostgreSQL } from "./types"; // Return an array of project_id's of projects that have the always_running run_quota set, // but are not in the running or starting state. // We only check for stable states, i.e. there is no state transition going on right now. // Ref: @cocalc/util/compute-states.js // Performance: // - only an `x IN <array>` clause uses the index, not a `NOT IN`. // - settings ->> 'always_running' is indexed as TEXT, hence we match on the string "1" (no INT conversations) export async function projects_that_need_to_be_started( database: PostgreSQL, limit = 10 ): Promise<string[]> { const result = await database.async_query({ query: `SELECT project_id FROM projects WHERE deleted IS NOT TRUE AND (run_quota ->> 'always_running' = 'true' OR (settings ->> 'always_running')::TEXT = '1') AND (state ->> 'state' IN ('archived', 'closed', 'opened') OR state IS NULL) LIMIT ${limit}`, }); const projects: string[] = []; for (const row of result.rows) { projects.push(row.project_id); } return projects; // TODO: as mentioned above, need to also handle always_running coming from applied licenses, // which will be way more complicated. } export async function init_start_always_running_projects( database: PostgreSQL, interval_s: number = 15 ): Promise<void> { while (true) { try { for (const project_id of await projects_that_need_to_be_started( database )) { const compute_server = (database as any).compute_server; if (compute_server == null) continue; // not initialized (?) const project = compute_server(project_id); project.start(); // we fire this off, but do not wait on it } } catch (err) { console.warn("init_start_always_running_projects", err); } await delay(interval_s * 1000); } }