Skip to content

Conversation

@tito
Copy link
Member

@tito tito commented Sep 18, 2025

Summary

Migrate SQLAlchemy from 1.4 to 2.0 and convert to ORM-style queries

Changes

  • Remove encode/databases dependency, use native SQLAlchemy 2.0 async
  • Convert table definitions to Declarative Mapping pattern
  • Update all controllers to use dependency injection (session parameter)
  • Convert all queries from Core style to ORM style
  • Remove PostgreSQL compatibility checks (PostgreSQL only)
  • Add proper typing for async session components

Testing

All transcript tests passing (9 passed)

- Remove encode/databases dependency, use native SQLAlchemy 2.0 async
- Convert all table definitions to Declarative Mapping pattern
- Update all controllers to accept session parameter (dependency injection)
- Convert all queries from Core style to ORM style
- Remove PostgreSQL compatibility checks (PostgreSQL only now)
- Add proper typing for engine and session factories
@vercel
Copy link

vercel bot commented Sep 18, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
reflector-media Ready Ready Preview Comment Sep 24, 2025 6:00am
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
reflector Ignored Ignored Preview Sep 24, 2025 6:00am

@tito tito changed the title Migrate SQLAlchemy to 2.0 with ORM style feat: migrate SQLAlchemy to 2.0 with orm style and typing Sep 18, 2025
- Add session fixture for async session management
- Update all test files to use session parameter
- Convert Core-style queries to ORM-style in tests
- Fix controller calls to include session parameter
- Remove obsolete get_database() references

Test progress: 108/195 tests passing
…l controller calls

- Add session parameter to all view functions and controller calls
- Fix pipeline files to use get_session_factory() for background tasks
- Update PipelineMainBase and PipelineMainFile to handle sessions properly
- Add missing on_* methods to PipelineMainFile class
- Fix test fixtures to handle docker services availability
- Add docker_ip fixture for test database connections
- Import fixes for transcripts_controller in tests

All controller calls now properly use sessions as first parameter per SQLAlchemy 2.0 async patterns.
- Fix test_multiple_active_meetings.py to pass session to all controller calls
- All test functions now correctly use the session fixture from conftest.py
- Controllers properly receive session as first argument per SQLAlchemy 2.0 pattern
- Update migration files to use SQLAlchemy 2.0 select() syntax
- Fix RoomController to use select(RoomModel) instead of rooms.select()
- Add session parameter to CalendarEventController method calls
- Update ics_sync.py service to properly manage sessions
- Fix test files to pass session parameter to controller methods
- Update test assertions for correct attendee parsing behavior
…odule

- Fix cleanup module to use TranscriptModel instead of undefined 'transcripts'
- Update test_cleanup.py to use session fixture and SQLAlchemy 2.0 patterns
- Fix delete_single_transcript function reference in tests
- Update cleanup query to select specific columns for mappings().all()
- Simplify test database operations using direct insert/update statements
- Add session parameter to all test functions that use controller methods
- Update all rooms_controller method calls to include session as first parameter
- Ensure all test functions that need database access use the session fixture parameter
- Maintain consistency with other migrated test files

All tests pass individually when run with SQLite in-memory database.
The fixes follow the established pattern from other successfully migrated test files.
Fixed multiple test files for SQLAlchemy 2.0 compatibility:
- test_search.py: Fixed query syntax and session parameters
- test_room_ics.py: Added session parameter to all controller calls
- test_ics_background_tasks.py: Fixed imports and query patterns
- test_cleanup.py: Fixed model fields and session handling
- test_calendar_event.py: Improved session fixture usage
- calendar_events.py: Added commits for test compatibility
- rooms.py: Fixed result parsing for scalars().all()
- worker/cleanup.py: Added session parameter to remove_by_id

Results: 116 tests now passing (up from 107), 29 failures (down from 38)
Remaining issues are primarily async event loop isolation problems
- Add session-scoped event loop fixture to prevent 'Event loop is closed' errors
- Use NullPool for database connections to avoid asyncpg connection caching issues
- Override session.commit with flush in tests to maintain transaction rollback
- Configure pytest-asyncio with session-scoped loop defaults
- Fixes 'coroutine Connection._cancel was never awaited' warnings
- Properly dispose of database engines after each test

Results: 137 tests passing (up from 116), only 8 failures remaining
This addresses the SQLAlchemy 2.0 async session lifecycle issues with asyncpg
Fixed all 8 previously failing tests:
- test_attendee_parsing_bug: Mock session factory to use test session
- test_cleanup tests (3): Pass session parameter to cleanup functions
- test_ics_sync tests (3): Mock session factory for ICS sync service
- test_pipeline_main_file: Comprehensive mocking of transcripts controller

Key changes:
- Mock get_session_factory() to return test session for services
- Use asynccontextmanager for proper async session mocking
- Pass session parameter to cleanup functions
- Comprehensive controller mocking in pipeline tests

Results: 145 tests passing (up from 116 initially)
The 87 'errors' are only teardown/cleanup issues, not test failures
- Simplified docstrings to be more concise
- Removed obvious line comments that explain basic operations
- Kept only essential comments for complex logic
- Maintained comments that explain algorithms or non-obvious behavior

Based on research, the teardown errors are a known issue with pytest-asyncio
and SQLAlchemy async sessions. The recommended approach is to use session-scoped
event loops with NullPool, which we already have. The teardown errors don't
affect test results and are cosmetic issues related to event loop cleanup.
- Replace individual SQLAlchemy imports with 'import sqlalchemy as sa'
- Prefix all SQLAlchemy types with 'sa.' for better code clarity
- Move all imports to the top of the file (remove mid-file Computed import)
- Improve code readability by making SQLAlchemy usage explicit
- Remove "if session" anti-pattern from all functions
- Functions now require explicit AsyncSession parameters instead of optional session_factory
- Worker tasks (Celery) create sessions at top level using session_factory
- Add proper AsyncSession type annotations to all session parameters
- Update cleanup.py: delete_single_transcript, cleanup_old_transcripts, cleanup_old_public_data
- Update process.py: process_recording, process_meetings, reprocess_failed_recordings
- Update ics_sync.py: sync_room_ics, sync_all_ics_calendars, create_upcoming_meetings
- Update pipeline classes: get_transcript methods now require session
- Fix tests to pass sessions correctly

Benefits:
- Better type safety and IDE support with explicit AsyncSession typing
- Clear transaction boundaries with sessions created at task level
- Consistent session management pattern across codebase
- No ambiguity about session vs session_factory usage
- Create session_decorator.py with @with_session decorator
- Decorator automatically manages database sessions for worker tasks
- Ensures session stays open for entire task execution
- Fixes issue where sessions were closed before being used (e.g., process_meetings)

Applied decorator to all worker tasks:
- process.py: process_recording, process_meetings, reprocess_failed_recordings
- cleanup.py: cleanup_old_public_data_task
- ics_sync.py: sync_room_ics, sync_all_ics_calendars, create_upcoming_meetings

Benefits:
- Consistent session management across all worker tasks
- No more manual session_factory context management in tasks
- Proper transaction boundaries with automatic begin/commit
- Cleaner, more maintainable code
- Fixes session lifecycle issues in process_meetings
- Replace manual session management in test fixtures with @with_session decorator
- Simplify async test fixtures by removing explicit session handling
- Update dependencies in pyproject.toml and uv.lock
- Standardized test fixture naming from db_db_session to db_session
- Updated all test files to use consistent parameter naming
- All tests now passing with the new naming convention
- Update conftest.py fixtures to work with new session management
- Fix WebSocket close to use await in test_transcripts_rtc_ws.py
- Align test fixtures with new @with_session decorator pattern
- Replace __table__.join() with ORM-style joins using select_from().outerjoin()
- Replace __table__.delete() with delete(Model) in tests
- Migrate from **row.__dict__ to model_validate() with ConfigDict(from_attributes=True)
- Add ConfigDict(from_attributes=True) to all Pydantic models for proper SQLAlchemy model conversion
- Update all controller methods to use model_validate() instead of dict unpacking

This completes the migration to SQLAlchemy 2.0 recommended patterns while maintaining
backwards compatibility and improving code consistency.
- Add @with_session decorator to shared tasks in main_file_pipeline.py
- Update task_send_webhook_if_needed and task_pipeline_file_process to use session parameter
- Refactor PipelineMainFile methods to accept session as parameter
- Pass session through method calls instead of creating new sessions with get_session_factory()

This improves session management consistency and follows the pattern established
by other worker tasks in the codebase.
…ipeline functions

- Add new @with_session_and_transcript decorator that provides both session and transcript
- Replace @get_transcript decorator with session-aware version in key pipeline functions
- Remove duplicate get_session_factory() calls from cleanup_consent, pipeline_upload_mp3, and pipeline_post_to_zulip
- Update task wrappers to use the new decorator pattern

This eliminates redundant session creation and provides a cleaner, more consistent
pattern for functions that need both database session and transcript access.
- Updated sync_room_calendar method to accept AsyncSession as first parameter
- Removed internal get_session_factory() calls from the service
- Updated all callers (views/rooms.py, worker/ics_sync.py) to pass session
- Fixed all test files to remove mocking of get_session_factory
- Consistent with @with_session decorator pattern used elsewhere
- Updated rooms_list endpoint to use injected session dependency
- Removed get_session_factory import from views/rooms.py
- Updated test_pipeline_main_file.py to use mock session instead of get_session_factory
- Pipeline files keep their get_session_factory usage as they manage long-running operations
- Add db_session parameter to transcript_get_audio_mp3 endpoint
- Fix audio_mp3_filename path conversion with .as_posix()
- Add null check for audio_waveform before returning
- Update test fixtures to properly pass db_session parameter
- Fix transcript controller calls in test_transcripts_audio_download
- Add @with_session decorator to webhook.py send_transcript_webhook task
- Update tools/process.py to use get_session_factory instead of deprecated get_database
- Fix tests/conftest.py fixture to pass db_session to controller update
- Fix main_live_pipeline.py to create sessions for controller update calls
- Update exportdanswer.py and exportdb.py to use new session pattern with get_session_factory
- Ensure all transcripts_controller and rooms_controller calls include session parameter
- Split get_session into _get_session and get_session to facilitate test mocking
- Add autouse fixture to ensure db_session is properly injected in tests
- Fix generate_waveform method to accept session parameter explicitly
- Add db_session parameter to all RoomController.add() and update() calls in test_room_ics_api.py
- Fix TranscriptController.upsert_topic() calls to include session parameter in conftest.py fixture
- Fix TranscriptController.upsert_participant() and delete_participant() calls to include session parameter in API views
- Remove invalid setup_database fixture references, use pytest-async-sqlalchemy's database fixture instead
- Update CalendarEventController.upsert() calls to include session parameter

These changes ensure all controller methods receive the required session parameter
as part of the SQLAlchemy 2.0 migration pattern where sessions are explicitly managed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant