feat: add direct PostgreSQL and ACK deployment support

This commit is contained in:
2026-08-12 19:12:00 +08:00
parent d0192081c7
commit c44274f098
55 changed files with 3317 additions and 1064 deletions

View File

@@ -1,3 +1,7 @@
-- Compatibility snapshot for existing Supabase deployments.
-- New PostgreSQL/RDS deployments must use `npm run db:migrate`; do not use this
-- file as an unversioned migration source.
create table if not exists assets (
id text primary key,
owner_id text not null,
@@ -89,6 +93,8 @@ alter table usage_events add column if not exists account_display_name text;
alter table usage_events add column if not exists tenant_id text;
alter table usage_events add column if not exists organization_id text;
alter table usage_events add column if not exists organization_name text;
alter table usage_events add column if not exists quantity integer not null default 1;
alter table usage_events add column if not exists estimated_unit text not null default 'job';
update usage_events as usage
set source = case
@@ -113,11 +119,6 @@ alter table usage_events alter column source set not null;
alter table usage_events alter column estimated_unit set default 'job';
alter table usage_events drop constraint if exists usage_events_job_id_fkey;
delete from usage_events as later
using usage_events as earlier
where later.job_id = earlier.job_id
and (later.created_at, later.id) > (earlier.created_at, earlier.id);
create table if not exists projects (
id text primary key,
owner_id text not null,
@@ -151,6 +152,20 @@ create unique index if not exists generation_jobs_idempotency_idx
on generation_jobs(owner_id, external_client_id, idempotency_key)
where external_client_id is not null and idempotency_key is not null;
create index if not exists usage_events_owner_created_idx on usage_events(owner_id, created_at desc);
do $$
begin
if exists (
select 1
from usage_events
group by job_id
having count(*) > 1
) then
raise exception using
errcode = '23505',
message = 'USAGE_EVENTS_DUPLICATE_JOB_ID: back up and clean duplicate usage_events.job_id rows before retrying this migration';
end if;
end;
$$;
create unique index if not exists usage_events_job_id_idx on usage_events(job_id);
create index if not exists usage_events_source_created_idx on usage_events(source, created_at desc);
create index if not exists usage_events_organization_created_idx on usage_events(organization_id, created_at desc);
@@ -163,6 +178,7 @@ create or replace function claim_generation_jobs(
)
returns setof generation_jobs
language plpgsql
set search_path = public, pg_temp
as $$
declare
v_now timestamptz := now();
@@ -194,6 +210,8 @@ begin
end;
$$;
revoke all on function claim_generation_jobs(text, integer, integer) from public;
create table if not exists platform_organizations (
id text primary key,
name text not null unique,
@@ -288,12 +306,61 @@ create table if not exists billing_ledger (
delta_fen bigint not null check (delta_fen <> 0),
balance_after_fen bigint not null check (balance_after_fen >= 0),
currency text not null default 'CNY' check (currency = 'CNY'),
idempotency_key text not null unique,
idempotency_key text not null,
description text not null,
metadata jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
do $$
declare
v_constraint record;
v_index record;
begin
for v_constraint in
select constraint_schema, constraint_name
from information_schema.table_constraints
where table_schema = current_schema()
and table_name = 'billing_ledger'
and constraint_type = 'UNIQUE'
and array(
select key_column_usage.column_name::text
from information_schema.key_column_usage
where key_column_usage.constraint_schema = table_constraints.constraint_schema
and key_column_usage.constraint_name = table_constraints.constraint_name
and key_column_usage.table_name = table_constraints.table_name
order by key_column_usage.ordinal_position
) = array['idempotency_key']::text[]
loop
execute format('alter table %I.%I drop constraint %I', current_schema(), 'billing_ledger', v_constraint.constraint_name);
end loop;
for v_index in
select indexes.schemaname, indexes.indexname
from pg_indexes as indexes
join pg_class as index_class on index_class.relname = indexes.indexname
join pg_namespace as index_namespace
on index_namespace.oid = index_class.relnamespace
and index_namespace.nspname = indexes.schemaname
join pg_index as index_metadata on index_metadata.indexrelid = index_class.oid
join pg_attribute as indexed_column
on indexed_column.attrelid = index_metadata.indrelid
and indexed_column.attnum = index_metadata.indkey[0]
left join pg_constraint as backing_constraint on backing_constraint.conindid = index_class.oid
where indexes.schemaname = current_schema()
and indexes.tablename = 'billing_ledger'
and index_metadata.indisunique
and index_metadata.indnkeyatts = 1
and indexed_column.attname = 'idempotency_key'
and backing_constraint.oid is null
loop
execute format('drop index %I.%I', v_index.schemaname, v_index.indexname);
end loop;
end;
$$;
create unique index if not exists billing_ledger_organization_idempotency_idx
on billing_ledger(organization_id, idempotency_key);
create index if not exists billing_ledger_organization_created_idx on billing_ledger(organization_id, created_at desc);
create index if not exists billing_ledger_account_created_idx on billing_ledger(account_id, created_at desc);
create index if not exists billing_ledger_job_idx on billing_ledger(job_id);
@@ -321,11 +388,13 @@ returns table (
delta_fen bigint
)
language plpgsql
set search_path = public, pg_temp
as $$
declare
v_existing billing_ledger%rowtype;
v_wallet billing_wallets%rowtype;
v_entry billing_ledger%rowtype;
v_account_id text;
begin
if p_currency <> 'CNY' then
raise exception 'BILLING_UNSUPPORTED_CURRENCY';
@@ -334,9 +403,29 @@ begin
raise exception 'BILLING_ZERO_DELTA';
end if;
select * into v_existing from billing_ledger where idempotency_key = p_idempotency_key;
v_account_id := case when p_kind in ('recharge', 'adjustment') then null else p_account_id end;
perform pg_advisory_xact_lock(
hashtextextended(jsonb_build_array(p_organization_id, p_idempotency_key)::text, 0)
);
select * into v_existing
from billing_ledger
where organization_id = p_organization_id
and idempotency_key = p_idempotency_key;
if found then
select * into v_wallet from billing_wallets where organization_id = v_existing.organization_id;
if v_existing.account_id is distinct from v_account_id
or v_existing.job_id is distinct from p_job_id
or v_existing.kind is distinct from p_kind
or v_existing.delta_fen is distinct from p_delta_fen
or v_existing.currency is distinct from p_currency
then
raise exception using
errcode = 'P0001',
message = 'BILLING_IDEMPOTENCY_PAYLOAD_MISMATCH';
end if;
select * into v_wallet from billing_wallets where organization_id = p_organization_id;
return query select v_existing.id, v_existing.balance_after_fen, v_wallet.balance_fen,
v_wallet.total_recharged_fen, v_wallet.total_charged_fen, v_existing.created_at,
v_wallet.updated_at, v_existing.delta_fen;
@@ -368,7 +457,7 @@ begin
balance_after_fen, currency, idempotency_key, description, metadata
) values (
p_ledger_id, p_organization_id,
case when p_kind in ('recharge', 'adjustment') then null else p_account_id end,
v_account_id,
p_job_id, p_kind, p_delta_fen,
v_wallet.balance_fen, p_currency, p_idempotency_key, p_description, coalesce(p_metadata, '{}'::jsonb)
) returning * into v_entry;
@@ -378,3 +467,5 @@ begin
v_wallet.updated_at, v_entry.delta_fen;
end;
$$;
revoke all on function billing_post_wallet_entry(text, text, text, text, text, bigint, text, text, text, jsonb) from public;