Skip to content

feat(rf-commissioning): add SQLite persistence module with repository architecture#232

Open
lisazacarias wants to merge 4 commits intoslaclab:mainfrom
lisazacarias:feat/rf-comm/database
Open

feat(rf-commissioning): add SQLite persistence module with repository architecture#232
lisazacarias wants to merge 4 commits intoslaclab:mainfrom
lisazacarias:feat/rf-comm/database

Conversation

@lisazacarias
Copy link
Copy Markdown
Collaborator

@lisazacarias lisazacarias commented Apr 18, 2026

This PR refactors the RF commissioning database layer from a monolithic CommissioningDatabase class into a repository-based architecture, improving separation of concerns and testability. It also adds an AGENTS.md documentation file to guide AI agents working with the codebase.

Key Changes

Architecture Refactoring

  • Extracted 6 focused repositories from the original CommissioningDatabase class:

    • RecordRepository - Cavity commissioning session persistence
    • QueryRepository - Read/query operations and workflow metadata
    • MeasurementRepository - Measurement history and notes
    • NotesRepository - General record-level notes
    • OperatorRepository - Approved operator name management
    • CryomoduleRepository - Cryomodule-level checkout records
  • Introduced BaseRepository with shared database helpers (serialization, versioning, conflict detection)

  • New helper modules:

    • database_errors.py - RecordConflictError exception
    • database_helpers.py - Pure functions for JSON parsing, note management, workflow state projection
    • database_schema.py - Schema initialization logic

Database Schema Evolution

  • Removed denormalized columns from commissioning_records: current_phase, overall_status, phase_status, phase_history
  • Workflow state now derived from normalized commissioning_runs and commissioning_phase_instances tables at query time
  • Unique constraint enforced per cavity coordinate (linac, cryomodule, cavity_number)
  • Dropped legacy index idx_active_record_per_cavity; active filtering now uses commissioning_runs.status

Behavior Changes

  • Records are only considered "active" when they have an associated workflow run with status = 'in_progress'
  • get_record_by_cavity(..., active_only=True) now filters via join to commissioning_runs
  • Workflow state (current_phase, overall_status, phase_status) computed via build_workflow_state() helper

Documentation

  • Added AGENTS.md with:
    • Big-picture architecture (EPICS-first hierarchy, eager MACHINE construction)
    • Developer workflows (Python 3.12+, pytest, PyDM offscreen testing)
    • Project conventions (custom PV wrapper, PVBatch, structured logging, platform paths)
    • Integration points (EPICS/caproto, PyDM/Qt, tmux watchers, SQLite persistence)
    • High-signal file map for navigation

Testing

  • 10 new test files covering repositories, helpers, schema, and error handling (266 total test lines)
  • Tests verify:
    • Foreign key enforcement
    • Optimistic locking conflict detection
    • Active/inactive record filtering via workflow runs
    • Note append/update operations with versioning
    • Measurement history serialization of domain models
    • Schema idempotency and index creation
    • Workflow state projection from normalized tables

Migration Notes

  • No data migration required - existing databases will initialize missing tables/columns on first initialize() call
  • API surface unchanged - CommissioningDatabase maintains all public methods; internal implementation delegates to repositories
  • Backward compatible - Handles legacy note formats (non-list JSON) gracefully

Files Changed

  • New: 17 files (1 doc, 9 implementation, 7 test)
  • Modified: None (pure addition)

Motivation: This refactoring prepares the codebase for concurrent multi-user workflows by centralizing conflict detection logic and making workflow state computation explicit and testable.

… architecture

- add  facade for RF commissioning persistence operations
- introduce persistence schema initialization, shared helpers, and conflict error handling
- split data access into focused repositories (records, queries, notes, measurements, operators, cryomodules)
- export persistence package entry points under
- add comprehensive persistence test coverage for database, schema, helpers, errors, and repositories
- add  with project-specific architecture and workflow guidance
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new SQLite-backed persistence layer for RF commissioning, using a repository architecture to separate schema/init, record CRUD, workflow/measurement queries, and note/operator/cryomodule persistence, along with a comprehensive new test suite and agent-facing project guidance.

Changes:

  • Introduces RF commissioning SQLite schema initialization, shared helpers, and optimistic-locking conflict errors.
  • Adds repository classes for records, queries, measurements, notes, operators, and cryomodules, wrapped by a CommissioningDatabase facade.
  • Adds extensive pytest coverage for schema, helpers, errors, and repository behaviors, plus AGENTS.md workflow/architecture guidance.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/applications/rf_commissioning/models/persistence/test_database_schema.py Verifies schema tables/columns/indexes and idempotent init.
tests/applications/rf_commissioning/models/persistence/test_database_helpers.py Covers JSON parsing, note helpers, workflow state derivation, and serialization helpers.
tests/applications/rf_commissioning/models/persistence/test_database_errors.py Validates optimistic-locking conflict exception context/message.
tests/applications/rf_commissioning/models/persistence/test_database.py End-to-end DB behaviors: FK enforcement, conflicts, summaries, active record logic, stats, notes migration handling.
tests/applications/rf_commissioning/models/persistence/repositories/test_queries_cryomodules.py Exercises query + cryomodule repository round-trips and conflict detection.
tests/applications/rf_commissioning/models/persistence/repositories/test_notes_measurements_operators.py Covers operator normalization, versioned general notes, and measurement note editing flows.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/base.py Adds shared repository serialization + optimistic-lock helpers.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/records.py Implements record persistence and workflow-state loading.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/queries.py Adds browsing/query APIs, summaries, active-record selection, deletion, workflow metadata reads.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/notes.py Implements versioned general notes storage/editing.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/measurements.py Implements measurement history persistence and note append/update utilities.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/operators.py Adds operator list persistence with normalization/deduplication.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/cryomodules.py Adds cryomodule checkout record persistence with optimistic locking.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/repositories/init.py Exposes internal repository implementations.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/database_schema.py Defines SQLite schema (records, workflow, measurements, operators, cryomodules) and indexes.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/database_helpers.py Adds shared JSON/note/workflow-state helpers.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/database_errors.py Adds RecordConflictError.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/database.py Provides CommissioningDatabase facade wiring repositories + connection management.
src/sc_linac_physics/applications/rf_commissioning/models/persistence/init.py Exports persistence entry points.
AGENTS.md Adds repo architecture + workflow guidance for new agents/contributors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/sc_linac_physics/applications/rf_commissioning/models/persistence/database.py Outdated
…b helpers

Enforce retention-safe behavior by raising RecordDeletionDisabledError
instead of deleting commissioning records from persistence APIs.

Also tighten schema foreign key ON DELETE actions for normalized workflow
tables and remove unused duplicate helper wrappers from CommissioningDatabase
that duplicated BaseRepository logic.

Update persistence exports and tests to cover deletion policy, error context,
and expected schema FK delete actions.
Prevent AttributeError in record browsing when legacy/corrupted
 payloads are valid JSON but not objects.

Only map piezo summary fields when decoded payload is a dict, and add
parametrized regression tests for list/string/number JSON payloads.
@lisazacarias lisazacarias requested a review from a team April 18, 2026 01:38
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.

2 participants