7.3 KiB
Data Model: Migration UI Improvements
Date: 2025-12-27 | Status: Draft
Entities
1. Task (Extended)
Source: backend/src/core/task_manager.py
Fields:
id: UUID- Unique task identifiertype: str- Task type (e.g., "migration")status: TaskStatus- Current status (extended enum)start_time: datetime- When task was createdend_time: datetime | None- When task completed (if applicable)logs: List[LogEntry]- Task execution logscontext: Dict- Task-specific datainput_required: bool- Whether task is awaiting user inputinput_request: Dict | None- Details about required input (for AWAITING_INPUT state)
New Status Values:
AWAITING_INPUT- Task is paused waiting for user input (e.g., password)
Relationships:
- Has many:
LogEntry - Belongs to:
Migration(if migration task)
Validation Rules:
idmust be unique and non-nullstatusmust be valid TaskStatus enum valuestart_timemust be set on creationinput_requestrequired when status isAWAITING_INPUT
State Transitions:
graph LR
PENDING --> RUNNING
RUNNING --> SUCCESS
RUNNING --> FAILED
RUNNING --> AWAITING_INPUT
AWAITING_INPUT --> RUNNING
AWAITING_INPUT --> FAILED
2. LogEntry
Source: Existing in codebase
Fields:
timestamp: datetime- When log entry was createdlevel: str- Log level (INFO, WARNING, ERROR, etc.)message: str- Log messagecontext: Dict | None- Additional context data
Validation Rules:
timestampmust be setlevelmust be valid log levelmessagemust be non-empty
3. DatabasePasswordRequest (New)
Source: New entity for password prompts
Fields:
database_name: str- Name of database requiring passwordconnection_string: str | None- Partial connection string (without password)error_message: str | None- Original error messageattempt_count: int- Number of password attempts
Validation Rules:
database_namemust be non-emptyattempt_countmust be >= 0
Relationships:
- Embedded in:
Task.input_request
4. TaskListResponse (API DTO)
Fields:
tasks: List[TaskSummary]- List of task summariestotal: int- Total number of taskslimit: int- Pagination limitoffset: int- Pagination offset
5. TaskSummary (API DTO)
Fields:
id: UUID- Task IDtype: str- Task typestatus: str- Current statusstart_time: datetime- Start timeend_time: datetime | None- End time (if completed)requires_input: bool- Whether task needs user input
6. TaskLogResponse (API DTO)
Fields:
task_id: UUID- Task IDlogs: List[LogEntry]- Task logsstatus: str- Current task status
7. PasswordPromptRequest (API DTO)
Fields:
task_id: UUID- Task IDpasswords: Dict[str, str]- Database name to password mapping
Validation Rules:
task_idmust exist and be in AWAITING_INPUT state- All required databases must be provided
API Contracts
1. GET /api/tasks - List Tasks
Purpose: Retrieve list of recent migration tasks
Parameters:
limit: int(query, optional) - Pagination limit (default: 10)offset: int(query, optional) - Pagination offset (default: 0)status: str(query, optional) - Filter by status
Response: TaskListResponse
Example:
{
"tasks": [
{
"id": "abc-123",
"type": "migration",
"status": "RUNNING",
"start_time": "2025-12-27T09:47:12Z",
"end_time": null,
"requires_input": false
}
],
"total": 1,
"limit": 10,
"offset": 0
}
2. GET /api/tasks/{task_id}/logs - Get Task Logs
Purpose: Retrieve detailed logs for a specific task
Parameters: None
Response: TaskLogResponse
Example:
{
"task_id": "abc-123",
"status": "AWAITING_INPUT",
"logs": [
{
"timestamp": "2025-12-27T09:47:12Z",
"level": "ERROR",
"message": "Must provide a password for the database",
"context": {
"database": "PostgreSQL"
}
}
]
}
3. POST /api/tasks/{task_id}/resume - Resume Task with Input
Purpose: Provide required input and resume a paused task
Request Body: PasswordPromptRequest
Response:
{
"success": true,
"message": "Task resumed successfully"
}
Error Responses:
404 Not Found- Task not found400 Bad Request- Invalid input or task not in AWAITING_INPUT state409 Conflict- Task already completed or failed
Database Schema Changes
Task Persistence (SQLite)
Table: persistent_tasks
Columns:
id TEXT PRIMARY KEY- Task IDstatus TEXT NOT NULL- Task statuscreated_at TEXT NOT NULL- Creation timestampupdated_at TEXT NOT NULL- Last update timestampinput_request JSON- Serialized input request datacontext JSON- Serialized task context
Indexes:
idx_statusonstatuscolumnidx_created_atoncreated_atcolumn
Event Flow
Normal Task Execution
sequenceDiagram
participant UI
participant API
participant TaskManager
participant MigrationPlugin
UI->>API: Start migration
API->>TaskManager: Create task
TaskManager->>MigrationPlugin: Execute
MigrationPlugin->>TaskManager: Update status (RUNNING)
MigrationPlugin->>TaskManager: Add logs
MigrationPlugin->>TaskManager: Update status (SUCCESS/FAILED)
Task with Password Requirement
sequenceDiagram
participant UI
participant API
participant TaskManager
participant MigrationPlugin
UI->>API: Start migration
API->>TaskManager: Create task
TaskManager->>MigrationPlugin: Execute
MigrationPlugin->>TaskManager: Update status (RUNNING)
MigrationPlugin->>TaskManager: Detect password error
TaskManager->>TaskManager: Update status (AWAITING_INPUT)
TaskManager->>API: Persist task (if needed)
API->>UI: Task status update
UI->>API: Get task logs
API->>UI: Return logs with error
UI->>User: Show password prompt
User->>UI: Provide password
UI->>API: POST /tasks/{id}/resume
API->>TaskManager: Resume task with password
TaskManager->>MigrationPlugin: Continue execution
MigrationPlugin->>TaskManager: Update status (RUNNING)
MigrationPlugin->>TaskManager: Complete task
Validation Rules
Task Creation
- Task ID must be unique
- Start time must be set
- Initial status must be PENDING
Task State Transitions
- Only RUNNING tasks can transition to AWAITING_INPUT
- Only AWAITING_INPUT tasks can be resumed
- Completed tasks (SUCCESS/FAILED) cannot be modified
Password Input
- All required databases must be provided
- Passwords must meet minimum complexity requirements
- Invalid passwords trigger new error and prompt again
Implementation Notes
-
Task Persistence: Only tasks in AWAITING_INPUT state will be persisted to handle backend restarts
-
Error Detection: Specific pattern matching for Superset "Must provide a password" errors
-
UI Integration: Real-time updates using existing WebSocket infrastructure
-
Security: Passwords are not permanently stored, only used for immediate task resumption
-
Performance: Basic pagination for task history to handle growth
Open Questions
None - All design decisions have been documented and validated against requirements.