mirror of https://github.com/coder/coder.git
82 lines
3.3 KiB
SQL
82 lines
3.3 KiB
SQL
-- Bumps the workspace deadline by the template's configured "activity_bump"
|
|
-- duration (default 1h). If the workspace bump will cross an autostart
|
|
-- threshold, then the bump is autostart + TTL. This is the deadline behavior if
|
|
-- the workspace was to autostart from a stopped state.
|
|
--
|
|
-- Max deadline is respected, and the deadline will never be bumped past it.
|
|
-- The deadline will never decrease.
|
|
-- name: ActivityBumpWorkspace :exec
|
|
WITH latest AS (
|
|
SELECT
|
|
workspace_builds.id::uuid AS build_id,
|
|
workspace_builds.deadline::timestamp with time zone AS build_deadline,
|
|
workspace_builds.max_deadline::timestamp with time zone AS build_max_deadline,
|
|
workspace_builds.transition AS build_transition,
|
|
provisioner_jobs.completed_at::timestamp with time zone AS job_completed_at,
|
|
templates.activity_bump AS activity_bump,
|
|
(
|
|
CASE
|
|
-- If the extension would push us over the next_autostart
|
|
-- interval, then extend the deadline by the full TTL (NOT
|
|
-- activity bump) from the autostart time. This will essentially
|
|
-- be as if the workspace auto started at the given time and the
|
|
-- original TTL was applied.
|
|
--
|
|
-- Sadly we can't define `activity_bump_interval` above since
|
|
-- it won't be available for this CASE statement, so we have to
|
|
-- copy the cast twice.
|
|
WHEN NOW() + (templates.activity_bump / 1000 / 1000 / 1000 || ' seconds')::interval > @next_autostart :: timestamptz
|
|
-- If the autostart is behind now(), then the
|
|
-- autostart schedule is either the 0 time and not provided,
|
|
-- or it was the autostart in the past, which is no longer
|
|
-- relevant. If autostart is > 0 and in the past, then
|
|
-- that is a mistake by the caller.
|
|
AND @next_autostart > NOW()
|
|
THEN
|
|
-- Extend to the autostart, then add the activity bump
|
|
((@next_autostart :: timestamptz) - NOW()) + CASE
|
|
WHEN templates.allow_user_autostop
|
|
THEN (workspaces.ttl / 1000 / 1000 / 1000 || ' seconds')::interval
|
|
ELSE (templates.default_ttl / 1000 / 1000 / 1000 || ' seconds')::interval
|
|
END
|
|
|
|
-- Default to the activity bump duration.
|
|
ELSE
|
|
(templates.activity_bump / 1000 / 1000 / 1000 || ' seconds')::interval
|
|
END
|
|
) AS ttl_interval
|
|
FROM workspace_builds
|
|
JOIN provisioner_jobs
|
|
ON provisioner_jobs.id = workspace_builds.job_id
|
|
JOIN workspaces
|
|
ON workspaces.id = workspace_builds.workspace_id
|
|
JOIN templates
|
|
ON templates.id = workspaces.template_id
|
|
WHERE workspace_builds.workspace_id = @workspace_id::uuid
|
|
ORDER BY workspace_builds.build_number DESC
|
|
LIMIT 1
|
|
)
|
|
UPDATE
|
|
workspace_builds wb
|
|
SET
|
|
updated_at = NOW(),
|
|
deadline = CASE
|
|
WHEN l.build_max_deadline = '0001-01-01 00:00:00+00'
|
|
-- Never reduce the deadline from activity.
|
|
THEN GREATEST(wb.deadline, NOW() + l.ttl_interval)
|
|
ELSE LEAST(GREATEST(wb.deadline, NOW() + l.ttl_interval), l.build_max_deadline)
|
|
END
|
|
FROM latest l
|
|
WHERE wb.id = l.build_id
|
|
AND l.job_completed_at IS NOT NULL
|
|
-- We only bump if the template has an activity bump duration set.
|
|
AND l.activity_bump > 0
|
|
AND l.build_transition = 'start'
|
|
-- We only bump if the raw interval is positive and non-zero.
|
|
AND l.ttl_interval > '0 seconds'::interval
|
|
-- We only bump if workspace shutdown is manual.
|
|
AND l.build_deadline != '0001-01-01 00:00:00+00'
|
|
-- We only bump when 5% of the deadline has elapsed.
|
|
AND l.build_deadline - (l.ttl_interval * 0.95) < NOW()
|
|
;
|