fix(mobile-recording): never lose a meeting capture on offline stop, oversize, or re-record
This commit is contained in:
parent
80538c0f23
commit
5b1621d314
9 changed files with 1238 additions and 56 deletions
|
|
@ -0,0 +1,199 @@
|
|||
\set ON_ERROR_STOP on
|
||||
|
||||
-- Re-recording a meeting keeps its previous transcript until the new capture
|
||||
-- commits one (migration 20260929002700).
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE OR REPLACE FUNCTION pg_temp.assert_true(condition boolean, message text)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF condition IS NOT TRUE THEN
|
||||
RAISE EXCEPTION 'assertion_failed: %', message;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
INSERT INTO auth.users (
|
||||
id, aud, role, email, encrypted_password, email_confirmed_at,
|
||||
raw_app_meta_data, raw_user_meta_data, created_at, updated_at
|
||||
) VALUES (
|
||||
'81000000-0000-4000-8000-000000000001', 'authenticated', 'authenticated',
|
||||
'rerecord-owner@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
|
||||
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
|
||||
);
|
||||
|
||||
INSERT INTO public.meetings (
|
||||
id, user_id, title, status, raw_transcript, minutes_markdown, llm_model
|
||||
) VALUES
|
||||
(
|
||||
'82000000-0000-4000-8000-000000000001',
|
||||
'81000000-0000-4000-8000-000000000001',
|
||||
'Completed meeting', 'completed', 'old transcript', 'old minutes', 'old-llm'
|
||||
),
|
||||
(
|
||||
'82000000-0000-4000-8000-000000000002',
|
||||
'81000000-0000-4000-8000-000000000001',
|
||||
'Empty meeting', 'recording', NULL, NULL, NULL
|
||||
);
|
||||
|
||||
INSERT INTO public.transcripts (meeting_id, segment_index, timestamp_ms, duration_ms, text)
|
||||
VALUES
|
||||
('82000000-0000-4000-8000-000000000001', 0, 0, 1000, 'old segment 0'),
|
||||
('82000000-0000-4000-8000-000000000001', 1, 1000, 1000, 'old segment 1');
|
||||
|
||||
INSERT INTO public.audio_files (
|
||||
id, user_id, meeting_id, source, original_name, storage_key, mime_type,
|
||||
size_bytes, duration_ms, sha256, upload_status
|
||||
) VALUES (
|
||||
'83000000-0000-4000-8000-000000000001',
|
||||
'81000000-0000-4000-8000-000000000001',
|
||||
'82000000-0000-4000-8000-000000000001',
|
||||
'recording', 'old.wav',
|
||||
'81000000-0000-4000-8000-000000000001/imports/old.wav',
|
||||
'audio/wav', 32044, 1000, repeat('b', 64), 'uploaded'
|
||||
);
|
||||
|
||||
SET LOCAL ROLE authenticated;
|
||||
SELECT set_config(
|
||||
'request.jwt.claims',
|
||||
'{"sub":"81000000-0000-4000-8000-000000000001","role":"authenticated"}',
|
||||
true
|
||||
);
|
||||
|
||||
-- 1) Starting a re-record changes state only.
|
||||
SELECT public.mobile_begin_meeting_recording('82000000-0000-4000-8000-000000000001');
|
||||
SELECT pg_temp.assert_true(
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.meetings
|
||||
WHERE id = '82000000-0000-4000-8000-000000000001'
|
||||
AND status = 'recording'
|
||||
AND raw_transcript = 'old transcript'
|
||||
AND minutes_markdown = 'old minutes'
|
||||
),
|
||||
'begin keeps the previous transcript and minutes'
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
(SELECT count(*) FROM public.transcripts
|
||||
WHERE meeting_id = '82000000-0000-4000-8000-000000000001') = 2,
|
||||
'begin keeps the previous transcript rows'
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.audio_files
|
||||
WHERE id = '83000000-0000-4000-8000-000000000001'
|
||||
AND meeting_id = '82000000-0000-4000-8000-000000000001'
|
||||
),
|
||||
'begin keeps the previous audio linked'
|
||||
);
|
||||
|
||||
-- 2) Cancelling the re-record restores the completed meeting.
|
||||
SELECT public.mobile_cancel_meeting_recording('82000000-0000-4000-8000-000000000001');
|
||||
SELECT pg_temp.assert_true(
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.meetings
|
||||
WHERE id = '82000000-0000-4000-8000-000000000001'
|
||||
AND status = 'completed'
|
||||
AND error_message IS NULL
|
||||
AND raw_transcript = 'old transcript'
|
||||
),
|
||||
'cancel returns a meeting with content to completed'
|
||||
);
|
||||
|
||||
-- 3) Cancelling a first recording still reports an error.
|
||||
SELECT public.mobile_cancel_meeting_recording('82000000-0000-4000-8000-000000000002');
|
||||
SELECT pg_temp.assert_true(
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.meetings
|
||||
WHERE id = '82000000-0000-4000-8000-000000000002'
|
||||
AND status = 'error'
|
||||
AND error_message = 'Recording was cancelled before processing.'
|
||||
),
|
||||
'cancel of an empty meeting keeps the error outcome'
|
||||
);
|
||||
|
||||
-- 4) A committed re-record replaces the previous content.
|
||||
SELECT public.mobile_begin_meeting_recording('82000000-0000-4000-8000-000000000001');
|
||||
RESET ROLE;
|
||||
INSERT INTO public.audio_files (
|
||||
id, user_id, meeting_id, source, original_name, storage_key, mime_type,
|
||||
size_bytes, duration_ms, sha256, upload_status
|
||||
) VALUES (
|
||||
'83000000-0000-4000-8000-000000000002',
|
||||
'81000000-0000-4000-8000-000000000001',
|
||||
'82000000-0000-4000-8000-000000000001',
|
||||
'recording', 'new.wav',
|
||||
'81000000-0000-4000-8000-000000000001/imports/new.wav',
|
||||
'audio/wav', 32044, 2000, repeat('c', 64), 'uploaded'
|
||||
);
|
||||
SET LOCAL ROLE authenticated;
|
||||
SELECT set_config(
|
||||
'request.jwt.claims',
|
||||
'{"sub":"81000000-0000-4000-8000-000000000001","role":"authenticated"}',
|
||||
true
|
||||
);
|
||||
SELECT public.mobile_queue_meeting_recording('82000000-0000-4000-8000-000000000001', 2000);
|
||||
SELECT public.mobile_begin_meeting_processing(
|
||||
'82000000-0000-4000-8000-000000000001',
|
||||
'83000000-0000-4000-8000-000000000002',
|
||||
'mobile-meeting:rerecord:cccccccc'
|
||||
);
|
||||
SELECT public.mobile_complete_meeting_processing(
|
||||
'82000000-0000-4000-8000-000000000001',
|
||||
'83000000-0000-4000-8000-000000000002',
|
||||
'mobile-meeting:rerecord:cccccccc',
|
||||
'new transcript', 'ko', 'fixture-stt', 2000, 90
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.meetings
|
||||
WHERE id = '82000000-0000-4000-8000-000000000001'
|
||||
AND status = 'completed'
|
||||
AND raw_transcript = 'new transcript'
|
||||
AND minutes_markdown IS NULL
|
||||
AND llm_model IS NULL
|
||||
AND audio_storage_key = '81000000-0000-4000-8000-000000000001/imports/new.wav'
|
||||
),
|
||||
'completion replaces transcript and clears stale minutes'
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
(SELECT array_agg(text ORDER BY segment_index) FROM public.transcripts
|
||||
WHERE meeting_id = '82000000-0000-4000-8000-000000000001') = ARRAY['new transcript'],
|
||||
'completion removes every previous transcript row'
|
||||
);
|
||||
RESET ROLE;
|
||||
SELECT pg_temp.assert_true(
|
||||
(SELECT meeting_id FROM public.audio_files
|
||||
WHERE id = '83000000-0000-4000-8000-000000000001') IS NULL,
|
||||
'completion detaches the previous audio'
|
||||
);
|
||||
|
||||
-- 5) Replaying the committed job does not wipe minutes generated afterwards.
|
||||
UPDATE public.meetings
|
||||
SET minutes_markdown = 'fresh minutes'
|
||||
WHERE id = '82000000-0000-4000-8000-000000000001';
|
||||
SET LOCAL ROLE authenticated;
|
||||
SELECT set_config(
|
||||
'request.jwt.claims',
|
||||
'{"sub":"81000000-0000-4000-8000-000000000001","role":"authenticated"}',
|
||||
true
|
||||
);
|
||||
SELECT public.mobile_complete_meeting_processing(
|
||||
'82000000-0000-4000-8000-000000000001',
|
||||
'83000000-0000-4000-8000-000000000002',
|
||||
'mobile-meeting:rerecord:cccccccc',
|
||||
'new transcript', 'ko', 'fixture-stt', 2000, 90
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.meetings
|
||||
WHERE id = '82000000-0000-4000-8000-000000000001'
|
||||
AND minutes_markdown = 'fresh minutes'
|
||||
),
|
||||
'a replayed completion keeps minutes generated from the committed transcript'
|
||||
);
|
||||
|
||||
RESET ROLE;
|
||||
ROLLBACK;
|
||||
Loading…
Add table
Add a link
Reference in a new issue