Add MusicWorkshop application
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
TASK_STATUS_PENDING = 'pending'
|
||||
TASK_STATUS_RUNNING = 'running'
|
||||
TASK_STATUS_COMPLETED = 'completed'
|
||||
TASK_STATUS_FAILED = 'failed'
|
||||
TASK_TYPE_INGEST = 'ingest'
|
||||
TASK_TYPE_REPAIR = 'repair'
|
||||
|
||||
STAGE_STATUS_PENDING = 'pending'
|
||||
STAGE_STATUS_RUNNING = 'running'
|
||||
STAGE_STATUS_COMPLETED = 'completed'
|
||||
STAGE_STATUS_SKIPPED = 'skipped'
|
||||
STAGE_STATUS_FAILED = 'failed'
|
||||
|
||||
ACTIVE_TASK_STATUSES = (TASK_STATUS_PENDING, TASK_STATUS_RUNNING)
|
||||
SCAN_PROGRESS_LOG_LIMIT = 50
|
||||
SCAN_PROGRESS_BATCH_SIZE = 20
|
||||
SCAN_PROGRESS_INTERVAL_SECONDS = 1.0
|
||||
PREPROCESS_PROGRESS_BATCH_SIZE = 20
|
||||
PREPROCESS_PROGRESS_INTERVAL_SECONDS = 1.0
|
||||
MATCH_PROGRESS_BATCH_SIZE = 20
|
||||
MATCH_PROGRESS_INTERVAL_SECONDS = 1.0
|
||||
DEDUPE_PROGRESS_BATCH_SIZE = 20
|
||||
DEDUPE_PROGRESS_INTERVAL_SECONDS = 1.0
|
||||
ORGANIZE_PROGRESS_BATCH_SIZE = 20
|
||||
ORGANIZE_PROGRESS_INTERVAL_SECONDS = 1.0
|
||||
TASK_WORKSPACE_ROOT = '/tmp/musicworkshop/tasks'
|
||||
|
||||
STAGE_IDS = (
|
||||
'scan',
|
||||
'preprocess',
|
||||
'match',
|
||||
'dedupe',
|
||||
'organize',
|
||||
'complete'
|
||||
)
|
||||
|
||||
REPAIR_STAGE_IDS = (
|
||||
'prepare',
|
||||
'execute',
|
||||
'complete'
|
||||
)
|
||||
|
||||
|
||||
def current_timestamp() -> str:
|
||||
return (
|
||||
datetime.now(timezone.utc)
|
||||
.replace(microsecond=0)
|
||||
.isoformat()
|
||||
.replace('+00:00', 'Z')
|
||||
)
|
||||
|
||||
|
||||
def create_pending_stage_states() -> dict[str, str]:
|
||||
return {stage_id: STAGE_STATUS_PENDING for stage_id in STAGE_IDS}
|
||||
|
||||
|
||||
def create_pending_repair_stage_states() -> dict[str, str]:
|
||||
return {stage_id: STAGE_STATUS_PENDING for stage_id in REPAIR_STAGE_IDS}
|
||||
|
||||
|
||||
def create_scan_failed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_FAILED,
|
||||
'preprocess': STAGE_STATUS_PENDING,
|
||||
'match': STAGE_STATUS_PENDING,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_FAILED
|
||||
}
|
||||
|
||||
|
||||
def create_scan_completed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_PENDING,
|
||||
'match': STAGE_STATUS_PENDING,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_preprocess_running_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_RUNNING,
|
||||
'match': STAGE_STATUS_PENDING,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_preprocess_completed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_PENDING,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_preprocess_failed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_FAILED,
|
||||
'match': STAGE_STATUS_PENDING,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_FAILED
|
||||
}
|
||||
|
||||
|
||||
def create_match_running_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_RUNNING,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_match_completed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_match_failed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_FAILED,
|
||||
'dedupe': STAGE_STATUS_PENDING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_FAILED
|
||||
}
|
||||
|
||||
|
||||
def create_dedupe_running_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_RUNNING,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_dedupe_completed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_COMPLETED,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_dedupe_failed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_FAILED,
|
||||
'organize': STAGE_STATUS_PENDING,
|
||||
'complete': STAGE_STATUS_FAILED
|
||||
}
|
||||
|
||||
|
||||
def create_organize_running_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_COMPLETED,
|
||||
'organize': STAGE_STATUS_RUNNING,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_organize_completed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_COMPLETED,
|
||||
'organize': STAGE_STATUS_COMPLETED,
|
||||
'complete': STAGE_STATUS_PENDING
|
||||
}
|
||||
|
||||
|
||||
def create_organize_failed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_COMPLETED,
|
||||
'organize': STAGE_STATUS_FAILED,
|
||||
'complete': STAGE_STATUS_FAILED
|
||||
}
|
||||
|
||||
|
||||
def create_task_completed_stage_states() -> dict[str, str]:
|
||||
return {
|
||||
'scan': STAGE_STATUS_COMPLETED,
|
||||
'preprocess': STAGE_STATUS_COMPLETED,
|
||||
'match': STAGE_STATUS_COMPLETED,
|
||||
'dedupe': STAGE_STATUS_COMPLETED,
|
||||
'organize': STAGE_STATUS_COMPLETED,
|
||||
'complete': STAGE_STATUS_COMPLETED
|
||||
}
|
||||
|
||||
|
||||
def create_empty_scan_stats() -> dict[str, int]:
|
||||
return {
|
||||
'total_found': 0,
|
||||
'queued': 0,
|
||||
'skipped_locked': 0,
|
||||
'skipped_invalid': 0,
|
||||
'ignored_non_audio': 0
|
||||
}
|
||||
|
||||
|
||||
def create_empty_preprocess_stats() -> dict[str, int]:
|
||||
return {
|
||||
'input_items': 0,
|
||||
'output_items': 0,
|
||||
'split_parents': 0,
|
||||
'generated_children': 0,
|
||||
'converted_items': 0,
|
||||
'metadata_snapshots': 0,
|
||||
'fingerprints_ok': 0,
|
||||
'fingerprints_failed': 0,
|
||||
'failed_items': 0,
|
||||
'warning_items': 0
|
||||
}
|
||||
|
||||
|
||||
def create_empty_match_stats() -> dict[str, int]:
|
||||
return {
|
||||
'input_items': 0,
|
||||
'matched_authoritative': 0,
|
||||
'matched_fallback': 0,
|
||||
'low_score': 0,
|
||||
'not_found': 0,
|
||||
'provider_warnings': 0,
|
||||
'failed_items': 0
|
||||
}
|
||||
|
||||
|
||||
def create_empty_dedupe_stats() -> dict[str, int]:
|
||||
return {
|
||||
'input_items': 0,
|
||||
'library_candidates': 0,
|
||||
'batch_duplicates': 0,
|
||||
'library_duplicates': 0,
|
||||
'replaced_library_items': 0,
|
||||
'kept_items': 0,
|
||||
'failed_items': 0
|
||||
}
|
||||
|
||||
|
||||
def create_empty_organize_stats() -> dict[str, int]:
|
||||
return {
|
||||
'input_items': 0,
|
||||
'moved_items': 0,
|
||||
'renamed_items': 0,
|
||||
'collision_resolved': 0,
|
||||
'trashed_items': 0,
|
||||
'failed_items': 0
|
||||
}
|
||||
|
||||
|
||||
def create_empty_task_stats() -> dict[str, dict[str, int]]:
|
||||
return {
|
||||
'scan': create_empty_scan_stats(),
|
||||
'preprocess': create_empty_preprocess_stats(),
|
||||
'match': create_empty_match_stats(),
|
||||
'dedupe': create_empty_dedupe_stats(),
|
||||
'organize': create_empty_organize_stats()
|
||||
}
|
||||
|
||||
|
||||
def create_empty_repair_stats() -> dict[str, dict[str, int]]:
|
||||
return {
|
||||
'prepare': {
|
||||
'previewed_items': 0,
|
||||
'rejected_items': 0
|
||||
},
|
||||
'execute': {
|
||||
'succeeded_items': 0,
|
||||
'failed_items': 0,
|
||||
'moved_items': 0,
|
||||
'updated_metadata_items': 0,
|
||||
'ignored_items': 0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user