New token arch

This commit is contained in:
Urtzi Alfaro
2026-01-10 21:45:37 +01:00
parent cc53037552
commit bf1db7cb9e
26 changed files with 1751 additions and 107 deletions

View File

@@ -14,6 +14,20 @@ from sqlalchemy.dialects.postgresql import UUID
import uuid
def _index_exists(connection, index_name: str) -> bool:
"""Check if an index exists in the database."""
result = connection.execute(
sa.text("""
SELECT EXISTS (
SELECT 1 FROM pg_indexes
WHERE indexname = :index_name
)
"""),
{"index_name": index_name}
)
return result.scalar()
# revision identifiers, used by Alembic.
revision: str = '001_unified_initial_schema'
down_revision: Union[str, None] = None
@@ -226,6 +240,65 @@ def upgrade() -> None:
sa.PrimaryKeyConstraint('id')
)
# Add performance indexes for subscriptions table
# Get connection to check existing indexes
connection = op.get_bind()
# Index 1: Fast lookup by tenant_id with status filter
if not _index_exists(connection, 'idx_subscriptions_tenant_status'):
op.create_index(
'idx_subscriptions_tenant_status',
'subscriptions',
['tenant_id', 'status'],
unique=False,
postgresql_where=sa.text("status IN ('active', 'trial', 'trialing')")
)
# Index 2: Covering index to avoid table lookups (most efficient)
if not _index_exists(connection, 'idx_subscriptions_tenant_covering'):
op.execute("""
CREATE INDEX idx_subscriptions_tenant_covering
ON subscriptions (tenant_id, plan, status, next_billing_date, monthly_price, max_users, max_locations, max_products)
""")
# Index 3: Status and validity checks for batch operations
if not _index_exists(connection, 'idx_subscriptions_status_billing'):
op.create_index(
'idx_subscriptions_status_billing',
'subscriptions',
['status', 'next_billing_date'],
unique=False,
postgresql_where=sa.text("status IN ('active', 'trial', 'trialing')")
)
# Index 4: Quick lookup for tenant's active subscription (specialized)
if not _index_exists(connection, 'idx_subscriptions_active_tenant'):
op.execute("""
CREATE INDEX idx_subscriptions_active_tenant
ON subscriptions (tenant_id, status, plan, next_billing_date, max_users, max_locations, max_products)
WHERE status = 'active'
""")
# Index 5: Stripe subscription lookup (for webhook processing)
if not _index_exists(connection, 'idx_subscriptions_stripe_sub_id'):
op.create_index(
'idx_subscriptions_stripe_sub_id',
'subscriptions',
['stripe_subscription_id'],
unique=False,
postgresql_where=sa.text("stripe_subscription_id IS NOT NULL")
)
# Index 6: Stripe customer lookup (for customer-related operations)
if not _index_exists(connection, 'idx_subscriptions_stripe_customer_id'):
op.create_index(
'idx_subscriptions_stripe_customer_id',
'subscriptions',
['stripe_customer_id'],
unique=False,
postgresql_where=sa.text("stripe_customer_id IS NOT NULL")
)
# Create coupons table with tenant_id nullable to support system-wide coupons
op.create_table('coupons',
sa.Column('id', sa.UUID(), nullable=False),
@@ -372,6 +445,14 @@ def downgrade() -> None:
op.drop_index('idx_coupon_code_active', table_name='coupons')
op.drop_table('coupons')
# Drop subscriptions table indexes first
op.drop_index('idx_subscriptions_stripe_customer_id', table_name='subscriptions')
op.drop_index('idx_subscriptions_stripe_sub_id', table_name='subscriptions')
op.drop_index('idx_subscriptions_active_tenant', table_name='subscriptions')
op.drop_index('idx_subscriptions_status_billing', table_name='subscriptions')
op.drop_index('idx_subscriptions_tenant_covering', table_name='subscriptions')
op.drop_index('idx_subscriptions_tenant_status', table_name='subscriptions')
# Drop subscriptions table
op.drop_table('subscriptions')