CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/database/postgres/always-running.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { delay } from "awaiting";
7
import { PostgreSQL } from "./types";
8
9
// Return an array of project_id's of projects that have the always_running run_quota set,
10
// but are not in the running or starting state.
11
// We only check for stable states, i.e. there is no state transition going on right now.
12
// Ref: @cocalc/util/compute-states.js
13
// Performance:
14
// - only an `x IN <array>` clause uses the index, not a `NOT IN`.
15
// - settings ->> 'always_running' is indexed as TEXT, hence we match on the string "1" (no INT conversations)
16
export async function projects_that_need_to_be_started(
17
database: PostgreSQL,
18
limit = 10,
19
): Promise<string[]> {
20
const result = await database.async_query({
21
query: `SELECT project_id FROM projects
22
WHERE deleted IS NOT TRUE
23
AND (run_quota ->> 'always_running' = 'true' OR (settings ->> 'always_running')::TEXT = '1')
24
AND (state ->> 'state' IN ('archived', 'closed', 'opened') OR state IS NULL)
25
LIMIT ${limit}`,
26
});
27
const projects: string[] = [];
28
for (const row of result.rows) {
29
projects.push(row.project_id);
30
}
31
return projects;
32
// TODO: as mentioned above, need to also handle always_running coming from applied licenses,
33
// which will be way more complicated.
34
}
35
36
export async function init_start_always_running_projects(
37
database: PostgreSQL,
38
interval_s: number = 15,
39
): Promise<void> {
40
while (true) {
41
try {
42
for (const project_id of await projects_that_need_to_be_started(
43
database,
44
)) {
45
const projectControl = (database as any).projectControl;
46
if (projectControl == null) continue; // not initialized (?)
47
const project = projectControl(project_id);
48
project.start(); // we fire this off, but do not wait on it
49
}
50
} catch (err) {
51
console.warn("init_start_always_running_projects", err);
52
}
53
await delay(interval_s * 1000);
54
}
55
}
56
57