Main orchestrator module for Music Genre Updater.
This module handles the high-level coordination of all operations.
Orchestrator
Orchestrates the entire music update workflow.
Initialize the orchestrator with dependencies.
Parameters:
| Name |
Type |
Description |
Default |
deps
|
DependencyContainer
|
Dependency container with all required services
|
required
|
Source code in src/app/orchestrator.py
| def __init__(self, deps: DependencyContainer) -> None:
"""Initialize the orchestrator with dependencies.
Args:
deps: Dependency container with all required services
"""
self.deps = deps
self.music_updater = MusicUpdater(deps)
self.config = deps.app_config
self.console_logger = deps.console_logger
self.error_logger = deps.error_logger
|
run_command
async
Execute the appropriate command based on arguments.
Parameters:
| Name |
Type |
Description |
Default |
args
|
Namespace
|
Parsed command-line arguments from argparse.
|
required
|
Source code in src/app/orchestrator.py
| async def run_command(self, args: argparse.Namespace) -> None:
"""Execute the appropriate command based on arguments.
Args:
args: Parsed command-line arguments from argparse.
"""
# Reset per-run state
reset_cleaning_exceptions_log()
# Handle --fresh flag: clear all caches and snapshots
if getattr(args, "fresh", False):
self.console_logger.info("--fresh flag set: clearing all caches and snapshots...")
await self.deps.cache_service.clear()
self.deps.library_snapshot_service.clear_snapshot()
self.console_logger.info("All caches cleared. Will fetch fresh data from Music.app.")
command = getattr(args, "command", None)
# Check if Music app is running for commands that depend on it
if self._requires_music_app(command) and not is_music_app_running(self.error_logger):
self.console_logger.error(
"Music.app is not running - cannot execute '%s' command. Please start Music.app before running this script.",
command or "default",
)
return
# Set dry-run context if needed
if args.dry_run or getattr(args, "test_mode", False):
test_artists = set(self.config.development.test_artists)
mode = "test" if getattr(args, "test_mode", False) else "dry_run"
self.music_updater.set_dry_run_context(mode, test_artists)
# ALWAYS apply test_artists from config if configured (even in --force mode)
elif test_artists_config := set(self.config.development.test_artists):
self.console_logger.info("Using test_artists from config in normal mode: %s", sorted(test_artists_config))
self.music_updater.set_dry_run_context("normal", test_artists_config)
# Route to an appropriate command
match args.command:
case "clean_artist" | "clean":
await self._run_clean_artist(args)
case "update_years" | "years":
await self._run_update_years(args)
case "update_genres" | "genres":
await self._run_update_genres(args)
case "revert_years" | "revert":
await self._run_revert_years(args)
case "restore_release_years" | "restore":
await self._run_restore_release_years(args)
case "verify_database" | "verify-db":
await self._run_verify_database(args)
case "verify_pending" | "pending":
await self._run_verify_pending(args)
case "batch":
await self._run_batch(args)
case "rotate_keys" | "rotate-keys":
self._run_rotate_encryption_keys(args)
case _:
await self._run_main_workflow(args)
|