Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
50 lines
1.9 KiB
Python
50 lines
1.9 KiB
Python
"""Add last_seen_at and reason_closed to terminal_sessions
|
|
|
|
Revision ID: 0015
|
|
Revises: 0014
|
|
Create Date: 2024-12-18
|
|
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = '0015'
|
|
down_revision: Union[str, None] = '0014'
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# NOTE: SQLite cannot do `ALTER TABLE ... ADD COLUMN ... DEFAULT CURRENT_TIMESTAMP`.
|
|
# We use batch mode to recreate the table safely.
|
|
|
|
with op.batch_alter_table('terminal_sessions', recreate='always') as batch_op:
|
|
batch_op.add_column(sa.Column('last_seen_at', sa.DateTime(timezone=True), nullable=True))
|
|
batch_op.add_column(sa.Column('reason_closed', sa.String(30), nullable=True))
|
|
|
|
# Backfill last_seen_at from created_at for existing rows
|
|
op.execute("UPDATE terminal_sessions SET last_seen_at = created_at WHERE last_seen_at IS NULL")
|
|
|
|
# Enforce NOT NULL + default for future inserts (recreate table again for SQLite)
|
|
with op.batch_alter_table('terminal_sessions', recreate='always') as batch_op:
|
|
batch_op.alter_column('last_seen_at', nullable=False, server_default=sa.text('CURRENT_TIMESTAMP'))
|
|
|
|
# Create indexes for efficient queries
|
|
op.create_index('ix_terminal_sessions_user_status', 'terminal_sessions', ['user_id', 'status'])
|
|
op.create_index('ix_terminal_sessions_last_seen', 'terminal_sessions', ['last_seen_at'])
|
|
|
|
|
|
def downgrade() -> None:
|
|
# Drop indexes
|
|
op.drop_index('ix_terminal_sessions_last_seen', table_name='terminal_sessions')
|
|
op.drop_index('ix_terminal_sessions_user_status', table_name='terminal_sessions')
|
|
|
|
# Drop columns (batch mode for SQLite)
|
|
with op.batch_alter_table('terminal_sessions', recreate='always') as batch_op:
|
|
batch_op.drop_column('reason_closed')
|
|
batch_op.drop_column('last_seen_at')
|