db: add state and error_details to recording

This commit is contained in:
Johan Brandhorst-Satzkorn authored and Timothy Messier committed 2023-05-31 12:18:17 +00:00
1 parent e83f5bcd4c
commit 11893a8885
5 files changed
+131 -8

No files matched your search

@@ -7,6 +7,24 @@ begin;
comment on domain rec_timestamp is
'a nullable timestamp with a time zone used for start and end times of recordings';
create table recording_session_state_enm (
name text primary key
constraint only_predefined_states_allowed
check(name in ('unknown', 'started', 'available'))
);
comment on table recording_session_state_enm is
'recording_session_state_enm holds valid values for the state of a recording_session row.';
insert into recording_session_state_enm (name)
values
('unknown'),
('started'),
('available');
create trigger immutable_columns before update on recording_session_state_enm
for each row execute procedure immutable_columns('name');
create table recording_session (
public_id wt_public_id primary key,
storage_bucket_id wt_public_id not null
@@ -58,8 +76,22 @@ begin;
end_time rec_timestamp null
constraint end_time_null_or_after_start_time
check (end_time > start_time),
state text not null default 'started'
constraint recording_session_state_enm_fkey
references recording_session_state_enm (name)
on delete restrict
on update cascade,
error_details wt_sentinel not null default wt_to_sentinel('no error details'),
constraint recording_session_session_id_public_id_uq
unique (session_id, public_id)
unique (session_id, public_id),
-- Error details are allowed two different types of values:
-- - e'\ufffeno error details\uffff', the sentinel value for "no error details", only when the recording is in the started or available state.
-- - some error message when the recording is in the unknown state.
constraint error_details_set_iff_state_not_started
check (
(error_details = wt_to_sentinel('no error details') and state in ('started', 'available')) or
(error_details != wt_to_sentinel('no error details') and state = 'unknown')
)
);
comment on table recording_session is
'recording_session holds metadata for the recording of a session. It outlives the session itself.';
@@ -86,6 +118,9 @@ begin;
if new.session_id is null then
raise exception 'a new recorded session must have a session_id';
end if;
if new.state is not null and new.state != 'started' then
raise exception 'state can only be set to ''started'' on insert';
end if;
select * into strict _session
from session
@@ -160,6 +195,21 @@ begin;
create trigger insert_session_recording before insert on recording_session
for each row execute procedure insert_session_recording();
create function update_session_recording() returns trigger
as $$
begin
if new.state != old.state and old.state != 'started' then
raise exception 'state can only be updated once';
end if;
return new;
end;
$$ language plpgsql;
comment on function update_session_recording is
'update_session_recording is a before update trigger for the recording_session table.';
create trigger update_session_recording before update on recording_session
for each row execute procedure update_session_recording();
create table recording_connection (
public_id wt_public_id primary key,
session_id wt_public_id null, -- Can be null if associated session has been deleted
@@ -12,6 +12,8 @@ select
rs.update_time,
rs.start_time,
rs.end_time,
rs.state,
rs.error_details,
sb.scope_id as storage_bucket_scope_id,
-- fields that cover the user fields at creation time
uh.public_id as user_history_public_id,
+2
View File
@@ -17,6 +17,8 @@ const (
// ExternalIdNone is a Boundary sentinel indicating that no id was provided by an
// external system.
ExternalIdNone = "\ufffenone\uffff"
// ErrorDetailsNone is a Boundary sentinel indicating that there were no error details.
NoErrorDetails = "\ufffeno error details\uffff"
)
// Is returns true if s is a valid sentinel.
@@ -15,9 +15,9 @@ begin;
select wtt_load('widgets', 'iam', 'kms', 'auth', 'hosts', 'targets', 'sessions');
insert into recording_session
(public_id, storage_bucket_id, session_id)
(public_id, storage_bucket_id, session_id, state)
values
('sr_123456789', 'sb____global', 's2_____clare');
('sr_123456789', 'sb____global', 's2_____clare', 'started');
insert into session_connection
(public_id, session_id)
values
@@ -4,11 +4,13 @@
-- recording_session tests the following triggers:
-- insert_session_recording
-- set_once_columns
-- insert_session_recording
-- update_session_recording
-- and the following constraints:
-- end_time_null_or_after_start_time
begin;
select plan(44);
select plan(53);
select wtt_load('widgets', 'iam', 'kms', 'auth', 'hosts', 'targets', 'sessions');
select has_view('session_recording_aggregate', 'view for aggregating session recording info does not exist');
@@ -58,16 +60,24 @@ begin;
-- Try to insert row with null session id
prepare insert_invalid_recording_session as
insert into recording_session
(public_id, storage_bucket_id, session_id)
(public_id, storage_bucket_id, session_id, state)
values
('sr_________1', 'sb____global', null);
('sr_________1', 'sb____global', null, 'started');
select throws_ok('insert_invalid_recording_session', null, null, 'insert invalid recording_session succeeded');
-- Try to insert row with non-started state
prepare insert_with_invalid_state as
insert into recording_session
(public_id, storage_bucket_id, session_id, state)
values
('sr_________1', 'sb_________g', 's1_____clare', 'available');
select throws_ok('insert_with_invalid_state', null, null, 'insert invalid recording_session state succeeded');
prepare insert_recording_session as
insert into recording_session
(public_id, storage_bucket_id, session_id)
(public_id, storage_bucket_id, session_id, state)
values
('sr_________1', 'sb____global', 's2_____clare');
('sr_________1', 'sb____global', 's2_____clare', 'started');
select lives_ok('insert_recording_session');
prepare insert_recording_session_target_address as
@@ -85,6 +95,65 @@ begin;
where public_id = 'sr_________1';
select throws_ok('invalid_close_recording_session', '23514', null, 'setting end_time before start_time succeeded');
-- Try to set state to unknown without setting error_details
prepare update_state_to_unknown_without_error as
update recording_session set
state = 'unknown'
where public_id = 'sr_________1';
select throws_ok('update_state_to_unknown_without_error', 23514, null, 'updating the state to ''unknown'' without setting error_details succeeded');
-- Try to set state to available while setting error details to a non-sentinel value
prepare update_state_to_available_without_sentinel_error as
update recording_session set
state = 'available',
error_details = 'an actual error'
where public_id = 'sr_________1';
select throws_ok('update_state_to_available_without_sentinel_error', 23514, null, 'updating the state to ''available'' without setting error_details to the sentinel value succeeded');
-- Try to set state to unknown while setting error_details to the no error sentinel value
prepare update_state_to_unknown_with_sentinel_error as
update recording_session set
state = 'unknown',
error_details = wt_to_sentinel('no error details')
where public_id = 'sr_________1';
select throws_ok('update_state_to_unknown_with_sentinel_error', 23514, null, 'updating the state to ''unknown'' while setting error_details to the no error sentinel value succeeded');
-- Try to set error_details without updating state
prepare update_error_details_without_updating_state as
update recording_session set
error_details = 'some error'
where public_id = 'sr_________1';
select throws_ok('update_error_details_without_updating_state', 23514, null, 'setting error_details without updating the state succeeded');
prepare update_state_to_available as
update recording_session set
state = 'available'
where public_id = 'sr_________1';
select lives_ok('update_state_to_available');
-- Updating state again should error
prepare update_state_to_unknown as
update recording_session set
state = 'unknown',
error_details = 'some error'
where public_id = 'sr_________1';
select throws_ok('update_state_to_unknown', null, null, 'updating the state away from ''available'' succeeded');
prepare update_state_to_unknown_with_error as
update recording_session set
state = 'unknown',
error_details = 'some error'
where public_id = 'sr_________2';
select lives_ok('update_state_to_unknown_with_error');
-- Updating state again should error
prepare update_state_to_available_again as
update recording_session set
state = 'available',
error_details = wt_to_sentinel('no error details')
where public_id = 'sr_________2';
select throws_ok('update_state_to_available_again', null, null, 'updating the state away from ''unknown'' succeeded');
prepare close_recording_session as
update recording_session set
start_time = clock_timestamp()::timestamptz,