Files
threshold/internal/db/sqltest/tests/session/cancel_session.sql
T
Timothy Messier 3609658edd perf(session): Avoid select when canceling session (#5140)
When a resource relating to a session is deleted,
notably a target, host, or auth_token, the corresponding sessions are
marked as canceled via a database trigger that calls the cancel_session
function. This function was performing a select as part of the insert
call to ensure that it would not attempt to insert a session_sate of
canceled if it was an invalid state transition. However, since this
function was first introduced, there has been additional constraints
added that would prevent an invalid state transition. In addition,
performing a select as part of an insert increases the chances for
contention with other queries that interact with the session_state
table, especially since a large number of sessions and session_state
rows can be included in a single transaction when things like
auth_tokens or targets get deleted.

Now, the cancel_function will perform the insert, and catch any of the
potential violations, allowing the query to continue without needing to
perform the select, thus reduction the potential for contention.
2024-10-01 10:14:06 -04:00

115 lines
4.0 KiB
PL/PgSQL

-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: BUSL-1.1
begin;
select plan(22);
-- Canceling a terminated session should cause no errors, but should not change state.
prepare cancel_terminated as
select cancel_session('s1_____cindy');
-- to start s1_____cindy should have 2 states, and the terminated should be the active state.
select is(count(*), 2::bigint)
from session_state
where session_id = 's1_____cindy';
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____cindy'
and state = 'terminated'
and upper(active_time_range) is null;
-- now attempt to cancel
select lives_ok('cancel_terminated');
-- there should be no changes to the state
select is(count(*), 2::bigint)
from session_state
where session_id = 's1_____cindy';
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____cindy'
and state = 'terminated'
and upper(active_time_range) is null;
-- Canceling a canceling session should cause no errors, but should not change state.
prepare cancel_canceling as
select cancel_session('s1_____ciara');
-- to start s1_____ciara should have 2 states, and the canceling should be the active state.
select is(count(*), 2::bigint)
from session_state
where session_id = 's1_____ciara';
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____ciara'
and state = 'canceling'
and upper(active_time_range) is null;
-- now attempt to cancel
select lives_ok('cancel_canceling');
-- there should be no changes to the state
select is(count(*), 2::bigint)
from session_state
where session_id = 's1_____ciara';
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____ciara'
and state = 'canceling'
and upper(active_time_range) is null;
-- Canceling an active session should cause no errors and should result the state changing to canceling.
prepare cancel_active as
select cancel_session('s1_____carly');
-- to start s1_____carly should have 2 states, and the active should be the active state.
select is(count(*), 2::bigint)
from session_state
where session_id = 's1_____carly';
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____carly'
and state = 'active'
and upper(active_time_range) is null;
-- now attempt to cancel
select lives_ok('cancel_active');
-- there should be a new state and active should no long be the active state.
select is(count(*), 3::bigint)
from session_state
where session_id = 's1_____carly';
select is(count(*), 0::bigint)
from session_state
where session_id = 's1_____carly'
and state = 'active'
and upper(active_time_range) is null;
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____carly'
and state = 'canceling'
and upper(active_time_range) is null;
-- Canceling a pending session should cause no errors and should result the state changing to canceling.
prepare cancel_pending as
select cancel_session('s1_____clare');
-- to start s1_____clare should have 2 states, and the active should be the active state.
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____clare';
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____clare'
and state = 'pending'
and upper(active_time_range) is null;
-- now attempt to cancel
select lives_ok('cancel_pending');
-- there should be a new state and pending should no long be the active state.
select is(count(*), 2::bigint)
from session_state
where session_id = 's1_____clare';
select is(count(*), 0::bigint)
from session_state
where session_id = 's1_____clare'
and state = 'pending'
and upper(active_time_range) is null;
select is(count(*), 1::bigint)
from session_state
where session_id = 's1_____clare'
and state = 'canceling'
and upper(active_time_range) is null;
select * from finish();
rollback;