import getLogger from "@cocalc/backend/logger" ; import { callback2 } from "@cocalc/util/async-utils" ; import { db } from "@cocalc/database" ; import { DEFAULT_QUOTAS } from "@cocalc/util/upgrade-spec" ; import { BaseProject as Project } from "./base" ; const logger = getLogger ( "stop-idle-projects" ) ; async function stopIdleProjects ( stopProject ) { logger . info ( "stopping all idle projects" ) ; logger . debug ( "query database for all running projects" ) ; const runningProjects = ( await callback2 ( db ( ) . _query , { query : "SELECT project_id, EXTRACT(EPOCH FROM NOW() - last_edited) as idle_time, settings FROM projects WHERE state ->> 'state' = 'running'" , } ) ) . rows ; logger . debug ( "got " , runningProjects ) ; for ( const project of runningProjects ) { const { project_id , idle_time , settings } = project ; const mintime = settings ?. mintime ?? DEFAULT_QUOTAS . mintime ; const always_running = settings ?. always_running ?? false ; if ( ! always_running && idle_time > mintime ) { stopProject ( project_id ) ; } } } export default function init ( getProject ) { if ( process . env . COCALC_NO_IDLE_TIMEOUT ) { logger . info ( "NOT initializing idle project stop loop since COCALC_NO_IDLE_TIMEOUT to set" ) ; return ; } logger . info ( "initializing idle project stop loop (set environment variable COCALC_NO_IDLE_TIMEOUT to disable)" ) ; const stopProject = async ( project_id ) => { logger . info ( `stopping ${ project_id } due to idle timeout` ) ; try { ( await getProject ( project_id ) ) . stop ( ) ; logger . debug ( `stopped ${ project_id } successfully` ) ; } catch ( err ) { logger . error ( `error stopping ${ project_id } -- ${ err }` ) ; } } ; setInterval ( ( ) => { stopIdleProjects ( stopProject ) ; } , 60000 ) ; stopIdleProjects ( stopProject ) ; }