fix(consult): preserve streaming across disconnects
Staging Backend Quality Gate / validate (push) Successful in 12m47s
Staging Backend Quality Gate / publish (push) Successful in 31m1s

This commit is contained in:
Jesse_Chen
2026-08-08 21:34:03 +08:00
parent c16c9bfbde
commit 32b683ebef
9 changed files with 1529 additions and 179 deletions
@@ -0,0 +1,280 @@
begin;
alter table public.consultation_requests
add column if not exists session_id uuid references public.chat_sessions(id) on delete set null,
add column if not exists response_message jsonb;
alter table public.consultation_requests
drop constraint if exists consultation_requests_response_message_check;
alter table public.consultation_requests
add constraint consultation_requests_response_message_check
check (response_message is null or jsonb_typeof(response_message) = 'object');
create index if not exists consultation_requests_user_session_created_idx
on public.consultation_requests (user_id, session_id, created_at desc);
create index if not exists consultation_requests_user_status_created_idx
on public.consultation_requests (user_id, status, created_at desc);
drop function if exists public.reserve_consultation_usage(uuid, text, text, integer);
create or replace function public.reserve_consultation_usage(
p_user_id uuid,
p_request_id text,
p_session_id uuid,
p_requested_model_id text,
p_credit_cost integer
)
returns table(
success boolean,
reservation_id uuid,
source text,
credits integer,
subscription_id uuid,
reason text,
retry_after_seconds integer
)
language plpgsql
security definer
set search_path = ''
as $$
declare
v_authorization record;
begin
if p_user_id is null or p_session_id is null or btrim(coalesce(p_request_id, '')) = '' then
return query select false, null::uuid, null::text, null::integer,
null::uuid, 'invalid_request'::text, null::integer;
return;
end if;
perform pg_advisory_xact_lock(hashtextextended(p_user_id::text || ':' || btrim(p_request_id), 0));
if not exists (
select 1
from public.chat_sessions as session
where session.id = p_session_id
and session.user_id = p_user_id
and session.session_type = 'consultation'
) then
return query select false, null::uuid, null::text,
(select profile.credits from public.profiles as profile where profile.id = p_user_id),
null::uuid, 'session_missing'::text, null::integer;
return;
end if;
if exists (
select 1
from public.consultation_requests as request
where request.user_id = p_user_id
and request.request_id = btrim(p_request_id)
) then
return query select false, null::uuid, null::text,
(select profile.credits from public.profiles as profile where profile.id = p_user_id),
null::uuid, 'request_conflict'::text, null::integer;
return;
end if;
select * into v_authorization
from public.authorize_usage(
p_user_id,
'chat.standard',
p_requested_model_id,
btrim(p_request_id),
p_credit_cost
);
if coalesce(v_authorization.success, false) then
insert into public.consultation_requests(user_id, request_id, session_id, status)
values (p_user_id, btrim(p_request_id), p_session_id, 'reserved');
end if;
return query select
v_authorization.success,
v_authorization.reservation_id,
v_authorization.source,
v_authorization.credits,
v_authorization.subscription_id,
v_authorization.reason,
v_authorization.retry_after_seconds;
end;
$$;
revoke all on function public.reserve_consultation_usage(uuid, text, uuid, text, integer)
from public, anon, authenticated;
grant execute on function public.reserve_consultation_usage(uuid, text, uuid, text, integer)
to service_role;
do $$ begin
if exists(select 1 from pg_roles where rolname = 'admin_runtime') then
grant execute on function public.reserve_consultation_usage(uuid, text, uuid, text, integer)
to admin_runtime;
end if;
end $$;
create or replace function public.cancel_consultation_credit(p_user_id uuid, p_request_id text)
returns table(success boolean, credits integer, error_code text)
language plpgsql
security definer
set search_path = ''
as $$
declare
v_request public.consultation_requests%rowtype;
v_release record;
v_balance integer;
begin
if p_user_id is null or btrim(coalesce(p_request_id, '')) = '' then
return query select false, null::integer, 'invalid_request'::text;
return;
end if;
perform pg_advisory_xact_lock(hashtextextended(p_user_id::text || ':' || btrim(p_request_id), 0));
select request.* into v_request
from public.consultation_requests as request
where request.user_id = p_user_id
and request.request_id = btrim(p_request_id)
for update;
if not found then
return query select false, null::integer, 'request_missing'::text;
return;
end if;
select profile.credits into v_balance
from public.profiles as profile
where profile.id = p_user_id;
if v_request.status = 'completed' then
return query select false, v_balance, 'request_completed'::text;
return;
end if;
if v_request.status = 'cancelled' then
return query select true, v_balance, null::text;
return;
end if;
if v_request.status <> 'reserved' then
return query select false, v_balance, 'invalid_request_status'::text;
return;
end if;
select * into v_release
from public.release_usage(p_user_id, btrim(p_request_id), 'consultation_cancelled');
if not coalesce(v_release.success, false) then
return query select false, v_release.credits, v_release.error_code;
return;
end if;
update public.consultation_requests
set status = 'cancelled', updated_at = clock_timestamp()
where user_id = p_user_id
and request_id = btrim(p_request_id)
and status = 'reserved';
return query select true, v_release.credits, null::text;
end;
$$;
revoke all on function public.cancel_consultation_credit(uuid, text)
from public, anon, authenticated;
grant execute on function public.cancel_consultation_credit(uuid, text)
to service_role;
do $$ begin
if exists(select 1 from pg_roles where rolname = 'admin_runtime') then
grant execute on function public.cancel_consultation_credit(uuid, text)
to admin_runtime;
end if;
end $$;
create or replace function public.complete_consultation_response(
p_user_id uuid,
p_request_id text,
p_session_id uuid,
p_response_message jsonb,
p_actual_usage jsonb
)
returns table(success boolean, credits integer, error_code text)
language plpgsql
security definer
set search_path = ''
as $$
declare
v_request public.consultation_requests%rowtype;
v_settlement record;
v_balance integer;
begin
if p_user_id is null or p_session_id is null or btrim(coalesce(p_request_id, '')) = '' then
return query select false, null::integer, 'invalid_request'::text;
return;
end if;
if jsonb_typeof(p_response_message) <> 'object'
or p_response_message->>'role' <> 'assistant'
or btrim(coalesce(p_response_message->>'text', '')) = '' then
return query select false, null::integer, 'invalid_response_message'::text;
return;
end if;
perform pg_advisory_xact_lock(hashtextextended(p_user_id::text || ':' || btrim(p_request_id), 0));
select request.* into v_request
from public.consultation_requests as request
where request.user_id = p_user_id
and request.request_id = btrim(p_request_id)
and request.session_id = p_session_id
for update;
if not found then
return query select false, null::integer, 'request_missing'::text;
return;
end if;
if v_request.status = 'cancelled' then
return query select false, null::integer, 'request_cancelled'::text;
return;
end if;
if v_request.status = 'completed' then
select profile.credits into v_balance from public.profiles as profile where profile.id = p_user_id;
return query select v_request.response_message = p_response_message, v_balance,
case when v_request.response_message = p_response_message then null::text else 'response_conflict'::text end;
return;
end if;
update public.chat_sessions as session
set messages = session.messages || jsonb_build_array(p_response_message),
updated_at = clock_timestamp()
where session.id = p_session_id
and session.user_id = p_user_id
and session.session_type = 'consultation';
if not found then
return query select false, null::integer, 'session_missing'::text;
return;
end if;
update public.consultation_requests
set response_message = p_response_message,
updated_at = clock_timestamp()
where user_id = p_user_id and request_id = btrim(p_request_id);
select * into v_settlement
from public.complete_usage(p_user_id, btrim(p_request_id), coalesce(p_actual_usage, '{}'::jsonb));
if not coalesce(v_settlement.success, false) then
raise exception 'consultation_usage_settlement_failed:%', coalesce(v_settlement.error_code, 'unknown');
end if;
update public.consultation_requests
set status = 'completed', updated_at = clock_timestamp()
where user_id = p_user_id and request_id = btrim(p_request_id);
return query select true, v_settlement.credits, null::text;
end;
$$;
revoke all on function public.complete_consultation_response(uuid, text, uuid, jsonb, jsonb)
from public, anon, authenticated;
grant execute on function public.complete_consultation_response(uuid, text, uuid, jsonb, jsonb)
to service_role;
do $$ begin
if exists(select 1 from pg_roles where rolname = 'admin_runtime') then
grant execute on function public.complete_consultation_response(uuid, text, uuid, jsonb, jsonb)
to admin_runtime;
end if;
end $$;
commit;