forked from cardosofelipe/fast-next-template
- Introduced extensive tests for session cleanup, async session CRUD methods, and concurrent cleanup to ensure reliability and efficiency. - Enhanced `schemas/users.py` with reusable password strength validation logic. - Improved error handling in `admin.py` routes by replacing `detail` with `message` for consistency and readability.
79 lines
2.3 KiB
Python
79 lines
2.3 KiB
Python
"""add_performance_indexes
|
|
|
|
Revision ID: 1174fffbe3e4
|
|
Revises: fbf6318a8a36
|
|
Create Date: 2025-11-01 04:15:25.367010
|
|
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
import sqlalchemy as sa
|
|
|
|
from alembic import op
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = '1174fffbe3e4'
|
|
down_revision: Union[str, None] = 'fbf6318a8a36'
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
"""Add performance indexes for optimized queries."""
|
|
|
|
# Index for session cleanup queries
|
|
# Optimizes: DELETE WHERE is_active = FALSE AND expires_at < now AND created_at < cutoff
|
|
op.create_index(
|
|
'ix_user_sessions_cleanup',
|
|
'user_sessions',
|
|
['is_active', 'expires_at', 'created_at'],
|
|
unique=False,
|
|
postgresql_where=sa.text('is_active = false')
|
|
)
|
|
|
|
# Index for user search queries (basic trigram support without pg_trgm extension)
|
|
# Optimizes: WHERE email ILIKE '%search%' OR first_name ILIKE '%search%'
|
|
# Note: For better performance, consider enabling pg_trgm extension
|
|
op.create_index(
|
|
'ix_users_email_lower',
|
|
'users',
|
|
[sa.text('LOWER(email)')],
|
|
unique=False,
|
|
postgresql_where=sa.text('deleted_at IS NULL')
|
|
)
|
|
|
|
op.create_index(
|
|
'ix_users_first_name_lower',
|
|
'users',
|
|
[sa.text('LOWER(first_name)')],
|
|
unique=False,
|
|
postgresql_where=sa.text('deleted_at IS NULL')
|
|
)
|
|
|
|
op.create_index(
|
|
'ix_users_last_name_lower',
|
|
'users',
|
|
[sa.text('LOWER(last_name)')],
|
|
unique=False,
|
|
postgresql_where=sa.text('deleted_at IS NULL')
|
|
)
|
|
|
|
# Index for organization search
|
|
op.create_index(
|
|
'ix_organizations_name_lower',
|
|
'organizations',
|
|
[sa.text('LOWER(name)')],
|
|
unique=False
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
"""Remove performance indexes."""
|
|
|
|
# Drop indexes in reverse order
|
|
op.drop_index('ix_organizations_name_lower', table_name='organizations')
|
|
op.drop_index('ix_users_last_name_lower', table_name='users')
|
|
op.drop_index('ix_users_first_name_lower', table_name='users')
|
|
op.drop_index('ix_users_email_lower', table_name='users')
|
|
op.drop_index('ix_user_sessions_cleanup', table_name='user_sessions')
|