""" Bootstrap service — idempotent startup initialisation. Ensures a default media library exists as soon as the first user is available. Called from three places: 1. AppConfig.ready() – every server start (DB already populated) 2. post_migrate signal – after `manage.py migrate` runs 3. auth.setup_admin endpoint – immediately after the first user is created """ import logging logger = logging.getLogger(__name__) DEFAULT_LIBRARY_NAME = "Default Library" # One-shot flag: after the first request triggers the bootstrap, disconnect # the signal so we don't repeat the DB check on every subsequent request. _startup_bootstrap_done = False def ensure_default_library(): """ Create a default media library if none exists yet. Idempotent — safe to call multiple times; does nothing when a library already exists. Returns the newly-created Library, or None if no action was taken (either a library already exists, or no users exist yet to be the owner). """ from core.models import Library, AppUser if Library.objects.exists(): return None # Already bootstrapped # Need an owner — prefer the first superuser, fall back to any user. owner = ( AppUser.objects.filter(is_superuser=True).order_by("date_joined").first() or AppUser.objects.order_by("date_joined").first() ) if owner is None: # No users yet — setup_admin will call us again once the first user exists. logger.debug("ensure_default_library: no users yet, skipping.") return None library = Library.objects.create( owner_user=owner, name=DEFAULT_LIBRARY_NAME, visibility="public", description=( "Default media library. " "Add media sources here to start building your channels." ), ) logger.info( "Bootstrap: created default library '%s' (id=%d) owned by '%s'.", library.name, library.id, owner.username, ) return library # --------------------------------------------------------------------------- # Signal handlers — wired up in CoreConfig.ready() # --------------------------------------------------------------------------- def _on_post_migrate(sender, **kwargs): """Run bootstrap after every successful migration.""" try: ensure_default_library() except Exception as exc: # pragma: no cover logger.warning("ensure_default_library failed in post_migrate: %s", exc) def _on_first_request(sender, **kwargs): """ One-shot: run bootstrap on the very first HTTP request after server start. Disconnects itself immediately so subsequent requests pay zero overhead. """ global _startup_bootstrap_done if _startup_bootstrap_done: return _startup_bootstrap_done = True from django.core.signals import request_started request_started.disconnect(_on_first_request) try: ensure_default_library() except Exception as exc: # pragma: no cover logger.warning("ensure_default_library failed on first request: %s", exc)