homelab_automation/alembic/versions/0015_add_terminal_session_fields.py
Bruno Charest 5bc12d0729
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
Add terminal session management with heartbeat monitoring, idle timeout detection, session reuse logic, and command history panel UI with search and filtering capabilities
2025-12-18 13:49:40 -05:00

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')