604 lines
22 KiB
SQL
604 lines
22 KiB
SQL
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE TABLE IF NOT EXISTS model_catalog_providers (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
provider_key text NOT NULL UNIQUE,
|
|
display_name text NOT NULL,
|
|
provider_type text NOT NULL DEFAULT 'openai_compatible',
|
|
capability_schema jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
default_rate_limit_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
status text NOT NULL DEFAULT 'active',
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_model_catalog_provider_status
|
|
ON model_catalog_providers(status);
|
|
|
|
CREATE TABLE IF NOT EXISTS base_model_catalog (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
provider_id uuid REFERENCES model_catalog_providers(id) ON DELETE SET NULL,
|
|
provider_key text NOT NULL,
|
|
canonical_model_key text NOT NULL UNIQUE,
|
|
provider_model_name text NOT NULL,
|
|
model_type text NOT NULL,
|
|
display_name text NOT NULL,
|
|
capabilities jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
base_billing_config jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
default_rate_limit_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
pricing_version integer NOT NULL DEFAULT 1,
|
|
status text NOT NULL DEFAULT 'active',
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_base_model_catalog_provider
|
|
ON base_model_catalog(provider_key, model_type, status);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_base_model_catalog_capabilities
|
|
ON base_model_catalog USING gin(capabilities);
|
|
|
|
CREATE TABLE IF NOT EXISTS integration_platforms (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
provider text NOT NULL,
|
|
platform_key text NOT NULL UNIQUE DEFAULT ('platform_' || replace(gen_random_uuid()::text, '-', '')),
|
|
name text NOT NULL,
|
|
base_url text,
|
|
auth_type text NOT NULL DEFAULT 'bearer',
|
|
credentials jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
config jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
visibility_scope text NOT NULL DEFAULT 'global',
|
|
tenant_id text,
|
|
tenant_key text,
|
|
default_pricing_mode text NOT NULL DEFAULT 'inherit_discount',
|
|
default_discount_factor numeric NOT NULL DEFAULT 1,
|
|
retry_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
rate_limit_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
priority integer NOT NULL DEFAULT 100,
|
|
dynamic_priority integer,
|
|
status text NOT NULL DEFAULT 'enabled',
|
|
disabled_reason text,
|
|
cooldown_until timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
deleted_at timestamptz
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_integration_platforms_provider_status
|
|
ON integration_platforms(provider, status);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_integration_platforms_status_priority
|
|
ON integration_platforms(status, priority, dynamic_priority);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_integration_platforms_cooldown
|
|
ON integration_platforms(cooldown_until);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_integration_platforms_tenant_scope
|
|
ON integration_platforms(visibility_scope, tenant_id, tenant_key, status);
|
|
|
|
CREATE TABLE IF NOT EXISTS model_pricing_rules (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
scope_type text NOT NULL,
|
|
scope_id uuid,
|
|
resource_type text NOT NULL,
|
|
unit text NOT NULL,
|
|
base_price numeric NOT NULL,
|
|
currency text NOT NULL DEFAULT 'resource',
|
|
base_weight jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
dynamic_weight jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
effective_from timestamptz,
|
|
effective_to timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_model_pricing_scope
|
|
ON model_pricing_rules(scope_type, scope_id, resource_type);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_model_pricing_effective
|
|
ON model_pricing_rules(effective_from, effective_to);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_user_groups (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
group_key text NOT NULL UNIQUE,
|
|
name text NOT NULL,
|
|
description text,
|
|
source text NOT NULL DEFAULT 'gateway',
|
|
priority integer NOT NULL DEFAULT 100,
|
|
recharge_discount_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
billing_discount_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
rate_limit_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
quota_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
status text NOT NULL DEFAULT 'active',
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_user_groups_status_priority
|
|
ON gateway_user_groups(status, priority);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_tenants (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_key text NOT NULL UNIQUE,
|
|
source text NOT NULL DEFAULT 'gateway',
|
|
external_tenant_id text,
|
|
name text NOT NULL,
|
|
description text,
|
|
default_user_group_id uuid REFERENCES gateway_user_groups(id) ON DELETE SET NULL,
|
|
plan_key text,
|
|
billing_profile jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
rate_limit_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
auth_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
status text NOT NULL DEFAULT 'active',
|
|
synced_at timestamptz,
|
|
source_updated_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
deleted_at timestamptz,
|
|
UNIQUE(source, external_tenant_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_tenants_source_external
|
|
ON gateway_tenants(source, external_tenant_id)
|
|
WHERE external_tenant_id IS NOT NULL;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_tenants_status
|
|
ON gateway_tenants(status, created_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_users (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_key text NOT NULL UNIQUE,
|
|
source text NOT NULL DEFAULT 'gateway',
|
|
external_user_id text,
|
|
username text NOT NULL,
|
|
display_name text,
|
|
email text,
|
|
phone text,
|
|
avatar_url text,
|
|
password_hash text,
|
|
gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL,
|
|
tenant_id text,
|
|
tenant_key text,
|
|
default_user_group_id uuid REFERENCES gateway_user_groups(id) ON DELETE SET NULL,
|
|
roles jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
auth_profile jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
status text NOT NULL DEFAULT 'active',
|
|
last_login_at timestamptz,
|
|
synced_at timestamptz,
|
|
source_updated_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
deleted_at timestamptz,
|
|
UNIQUE(source, external_user_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_users_source_external
|
|
ON gateway_users(source, external_user_id)
|
|
WHERE external_user_id IS NOT NULL;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_users_status
|
|
ON gateway_users(status, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_users_tenant
|
|
ON gateway_users(tenant_id, tenant_key, status);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_user_group_memberships (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
group_id uuid NOT NULL REFERENCES gateway_user_groups(id) ON DELETE CASCADE,
|
|
principal_type text NOT NULL,
|
|
principal_id text NOT NULL,
|
|
source text NOT NULL DEFAULT 'gateway',
|
|
priority integer NOT NULL DEFAULT 100,
|
|
effective_from timestamptz,
|
|
effective_to timestamptz,
|
|
status text NOT NULL DEFAULT 'active',
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(group_id, principal_type, principal_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_group_membership_principal
|
|
ON gateway_user_group_memberships(principal_type, principal_id, status);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_group_membership_effective
|
|
ON gateway_user_group_memberships(effective_from, effective_to);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_tenant_invitations (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES gateway_tenants(id) ON DELETE CASCADE,
|
|
invite_code text NOT NULL UNIQUE,
|
|
role text NOT NULL DEFAULT 'user',
|
|
user_group_id uuid REFERENCES gateway_user_groups(id) ON DELETE SET NULL,
|
|
max_uses integer,
|
|
used_count integer NOT NULL DEFAULT 0,
|
|
expires_at timestamptz,
|
|
status text NOT NULL DEFAULT 'active',
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_by uuid REFERENCES gateway_users(id) ON DELETE SET NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_invitations_tenant
|
|
ON gateway_tenant_invitations(tenant_id, status);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_invitations_expiry
|
|
ON gateway_tenant_invitations(expires_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_api_keys (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL,
|
|
gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE CASCADE,
|
|
tenant_id text,
|
|
tenant_key text,
|
|
user_id text,
|
|
key_prefix text NOT NULL,
|
|
key_hash text NOT NULL UNIQUE,
|
|
name text NOT NULL,
|
|
scopes jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
user_group_id uuid REFERENCES gateway_user_groups(id) ON DELETE SET NULL,
|
|
rate_limit_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
quota_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
status text NOT NULL DEFAULT 'active',
|
|
expires_at timestamptz,
|
|
last_used_at timestamptz,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
deleted_at timestamptz
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_api_keys_owner
|
|
ON gateway_api_keys(gateway_user_id, status, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_api_keys_prefix
|
|
ON gateway_api_keys(key_prefix, status);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_wallet_accounts (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL,
|
|
gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE CASCADE,
|
|
tenant_id text,
|
|
tenant_key text,
|
|
user_id text,
|
|
currency text NOT NULL DEFAULT 'resource',
|
|
balance numeric NOT NULL DEFAULT 0,
|
|
frozen_balance numeric NOT NULL DEFAULT 0,
|
|
total_recharged numeric NOT NULL DEFAULT 0,
|
|
total_spent numeric NOT NULL DEFAULT 0,
|
|
status text NOT NULL DEFAULT 'active',
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(gateway_user_id, currency)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_wallet_accounts_tenant
|
|
ON gateway_wallet_accounts(gateway_tenant_id, status);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_wallet_transactions (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id uuid NOT NULL REFERENCES gateway_wallet_accounts(id) ON DELETE CASCADE,
|
|
gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL,
|
|
gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE SET NULL,
|
|
direction text NOT NULL,
|
|
transaction_type text NOT NULL,
|
|
amount numeric NOT NULL,
|
|
balance_before numeric NOT NULL,
|
|
balance_after numeric NOT NULL,
|
|
idempotency_key text,
|
|
reference_type text,
|
|
reference_id text,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_wallet_transactions_account
|
|
ON gateway_wallet_transactions(account_id, created_at DESC);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uniq_gateway_wallet_tx_idempotency
|
|
ON gateway_wallet_transactions(account_id, idempotency_key)
|
|
WHERE idempotency_key IS NOT NULL;
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_recharge_orders (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL,
|
|
gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE CASCADE,
|
|
tenant_id text,
|
|
tenant_key text,
|
|
user_id text,
|
|
amount numeric NOT NULL,
|
|
bonus_amount numeric NOT NULL DEFAULT 0,
|
|
payable_amount numeric NOT NULL,
|
|
currency text NOT NULL DEFAULT 'resource',
|
|
channel text NOT NULL DEFAULT 'manual',
|
|
status text NOT NULL DEFAULT 'created',
|
|
external_order_id text,
|
|
idempotency_key text,
|
|
paid_at timestamptz,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_recharge_orders_user
|
|
ON gateway_recharge_orders(gateway_user_id, created_at DESC);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uniq_gateway_recharge_order_idempotency
|
|
ON gateway_recharge_orders(gateway_user_id, idempotency_key)
|
|
WHERE idempotency_key IS NOT NULL;
|
|
|
|
CREATE TABLE IF NOT EXISTS platform_models (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
platform_id uuid NOT NULL REFERENCES integration_platforms(id) ON DELETE CASCADE,
|
|
base_model_id uuid REFERENCES base_model_catalog(id) ON DELETE SET NULL,
|
|
model_name text NOT NULL,
|
|
model_alias text,
|
|
model_type text NOT NULL,
|
|
display_name text NOT NULL DEFAULT '',
|
|
capability_override jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
capabilities jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
pricing_mode text NOT NULL DEFAULT 'inherit_discount',
|
|
discount_factor numeric,
|
|
billing_config_override jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
billing_config jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
permission_config jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
retry_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
rate_limit_policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
enabled boolean NOT NULL DEFAULT true,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(platform_id, model_name, model_type)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_platform_models_base
|
|
ON platform_models(base_model_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_platform_models_lookup
|
|
ON platform_models(model_type, model_name, enabled);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_platform_models_alias
|
|
ON platform_models(model_alias);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_platform_models_capabilities
|
|
ON platform_models USING gin(capabilities);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_tasks (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
external_task_id text,
|
|
kind text NOT NULL,
|
|
run_mode text NOT NULL DEFAULT 'production',
|
|
user_id text NOT NULL,
|
|
gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE SET NULL,
|
|
user_source text NOT NULL DEFAULT 'gateway',
|
|
gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL,
|
|
tenant_id text,
|
|
tenant_key text,
|
|
api_key_id text,
|
|
user_group_id uuid REFERENCES gateway_user_groups(id) ON DELETE SET NULL,
|
|
user_group_key text,
|
|
user_group_policy_snapshot jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
model text NOT NULL,
|
|
model_type text,
|
|
request jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
normalized_request jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
status text NOT NULL DEFAULT 'queued',
|
|
queue_key text NOT NULL DEFAULT 'default',
|
|
priority integer NOT NULL DEFAULT 100,
|
|
idempotency_key text,
|
|
remote_task_id text,
|
|
remote_task_payload jsonb,
|
|
simulation_profile jsonb,
|
|
simulation_seed text,
|
|
locked_by text,
|
|
locked_at timestamptz,
|
|
heartbeat_at timestamptz,
|
|
next_run_at timestamptz NOT NULL DEFAULT now(),
|
|
attempt_count integer NOT NULL DEFAULT 0,
|
|
max_attempts integer NOT NULL DEFAULT 1,
|
|
result jsonb,
|
|
billings jsonb,
|
|
error text,
|
|
error_code text,
|
|
error_message text,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
finished_at timestamptz
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_tasks_queue
|
|
ON gateway_tasks(status, next_run_at, priority, created_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_tasks_lease
|
|
ON gateway_tasks(status, heartbeat_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_tasks_user_created
|
|
ON gateway_tasks(user_id, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_tasks_external
|
|
ON gateway_tasks(external_task_id);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uniq_gateway_tasks_idempotency
|
|
ON gateway_tasks(user_id, idempotency_key)
|
|
WHERE idempotency_key IS NOT NULL;
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_task_attempts (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
|
|
attempt_no integer NOT NULL,
|
|
platform_id uuid REFERENCES integration_platforms(id) ON DELETE SET NULL,
|
|
platform_model_id uuid REFERENCES platform_models(id) ON DELETE SET NULL,
|
|
client_id text,
|
|
queue_key text NOT NULL,
|
|
status text NOT NULL,
|
|
retryable boolean NOT NULL DEFAULT false,
|
|
simulated boolean NOT NULL DEFAULT false,
|
|
remote_task_id text,
|
|
request_snapshot jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
response_snapshot jsonb,
|
|
error_code text,
|
|
error_message text,
|
|
started_at timestamptz NOT NULL DEFAULT now(),
|
|
finished_at timestamptz,
|
|
UNIQUE(task_id, attempt_no)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_attempts_task
|
|
ON gateway_task_attempts(task_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_attempts_client
|
|
ON gateway_task_attempts(client_id, started_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_task_events (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
|
|
seq bigint NOT NULL,
|
|
event_type text NOT NULL,
|
|
status text,
|
|
phase text,
|
|
progress numeric,
|
|
message text,
|
|
payload jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
simulated boolean NOT NULL DEFAULT false,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(task_id, seq)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_events_task_created
|
|
ON gateway_task_events(task_id, created_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_task_callback_outbox (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
|
|
event_id uuid REFERENCES gateway_task_events(id) ON DELETE SET NULL,
|
|
seq bigint NOT NULL,
|
|
callback_url text NOT NULL,
|
|
payload jsonb NOT NULL,
|
|
status text NOT NULL DEFAULT 'pending',
|
|
attempts integer NOT NULL DEFAULT 0,
|
|
next_attempt_at timestamptz NOT NULL DEFAULT now(),
|
|
last_error text,
|
|
delivered_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(task_id, seq, callback_url)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_task_callback_outbox_pending
|
|
ON gateway_task_callback_outbox(status, next_attempt_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_task_callback_outbox_task
|
|
ON gateway_task_callback_outbox(task_id, seq);
|
|
|
|
CREATE TABLE IF NOT EXISTS runtime_client_states (
|
|
client_id text PRIMARY KEY,
|
|
platform_id uuid REFERENCES integration_platforms(id) ON DELETE SET NULL,
|
|
provider text NOT NULL,
|
|
method_name text NOT NULL,
|
|
queue_key text NOT NULL,
|
|
running_count integer NOT NULL DEFAULT 0,
|
|
waiting_count integer NOT NULL DEFAULT 0,
|
|
limiter_ratio numeric NOT NULL DEFAULT 0,
|
|
cooldown_until timestamptz,
|
|
last_assigned_at timestamptz,
|
|
last_error text,
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_runtime_client_queue
|
|
ON runtime_client_states(queue_key, cooldown_until);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_runtime_client_platform
|
|
ON runtime_client_states(platform_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_upload_assets (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
task_id uuid REFERENCES gateway_tasks(id) ON DELETE SET NULL,
|
|
source text NOT NULL,
|
|
server_main_file_id text,
|
|
url text NOT NULL,
|
|
object_key text,
|
|
content_type text,
|
|
size bigint,
|
|
checksum text,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_upload_task
|
|
ON gateway_upload_assets(task_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_upload_file
|
|
ON gateway_upload_assets(server_main_file_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_retry_policies (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
scope_type text NOT NULL,
|
|
scope_key text NOT NULL,
|
|
enabled boolean NOT NULL DEFAULT true,
|
|
policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(scope_type, scope_key)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_rate_limit_policies (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
scope_type text NOT NULL,
|
|
scope_key text NOT NULL,
|
|
policy jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(scope_type, scope_key)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_rate_limit_counters (
|
|
scope_type text NOT NULL,
|
|
scope_key text NOT NULL,
|
|
metric text NOT NULL,
|
|
window_start timestamptz NOT NULL,
|
|
limit_value numeric NOT NULL,
|
|
used_value numeric NOT NULL DEFAULT 0,
|
|
reserved_value numeric NOT NULL DEFAULT 0,
|
|
reset_at timestamptz NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
PRIMARY KEY(scope_type, scope_key, metric, window_start)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_concurrency_leases (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
|
|
attempt_id uuid REFERENCES gateway_task_attempts(id) ON DELETE SET NULL,
|
|
scope_type text NOT NULL,
|
|
scope_key text NOT NULL,
|
|
lease_value numeric NOT NULL DEFAULT 1,
|
|
acquired_at timestamptz NOT NULL DEFAULT now(),
|
|
expires_at timestamptz NOT NULL,
|
|
released_at timestamptz
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_concurrency_leases_active
|
|
ON gateway_concurrency_leases(scope_type, scope_key, released_at, expires_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_concurrency_leases_task
|
|
ON gateway_concurrency_leases(task_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS settlement_outbox (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
|
|
event_type text NOT NULL DEFAULT 'task.settlement.requested',
|
|
payload jsonb NOT NULL,
|
|
status text NOT NULL DEFAULT 'pending',
|
|
attempts integer NOT NULL DEFAULT 0,
|
|
next_attempt_at timestamptz NOT NULL DEFAULT now(),
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(task_id, event_type)
|
|
);
|