optimize plex sync: docker exec + single async loop + version-controlled crontab#35
Open
steezeburger wants to merge 1 commit into
Open
optimize plex sync: docker exec + single async loop + version-controlled crontab#35steezeburger wants to merge 1 commit into
steezeburger wants to merge 1 commit into
Conversation
…d crontab Three independent improvements that together address the OOM-kills-bot problem caused by the every-10-minute plex sync: 1. dcp-django-admin.sh prefers \`docker compose exec\` against the running web container over \`docker compose run --rm\`. Each sync invocation no longer pays the cost of spinning up a fresh ~150 MB ephemeral container. Falls back to \`compose run\` when web isn't running (e.g. first migrate). Also reads POSTGRES_HOST from .env directly instead of spawning a container just to inspect env, and skips the confirmation prompt when stdin isn't a TTY (so cron and GitHub Actions don't hang). 2. SyncWithPlexCommand now does sync-then-async-fanout: phase 1 walks Plex movies and persists them; phase 2 runs ONE asyncio.run wrapping all enrichments inside a single shared aiohttp.ClientSession via asyncio.gather. The old code spun up a fresh event loop and ClientSession per movie. EnrichMovieActorsCommand.execute now takes an optional session parameter so the existing manual backfill command (manage.py enrich_actors) keeps working unchanged. 3. crontab.txt commits the schedule to the repo, plus a \`just install-crontab\` recipe to apply it on the server. No scheduler container required — the existing schedule is now version-controlled instead of living only on the VPS.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #34. Three changes that together address the OOM-kills-bot problem caused by the every-10-minute plex sync.
Summary
bin/dcp-django-admin.shprefersdocker compose execagainst the running web container instead ofdocker compose run --rm. Each invocation no longer spins up a brand-new ephemeral container (~100–150 MB peak on this image), which is what was pushing the host into OOM territory and taking the bot down. Falls back tocompose run --rmwhen web isn't running (e.g. during the very first migrate). Also readsPOSTGRES_HOSTfrom.envdirectly instead of spawning a container just to inspect env, and skips the confirmation prompt when stdin isn't a TTY (so cron / GitHub Actions / SSH don't hang).SyncWithPlexCommandasync refactor. Phase 1 walks Plex movies and persists them; Phase 2 runs ONEasyncio.runover all enrichments inside a single sharedaiohttp.ClientSessionviaasyncio.gather. The previous code spun up a fresh event loop andClientSessionper movie.EnrichMovieActorsCommand.executenow takes an optionalsession=parameter so the existing manual backfill (manage.py enrich_actors) keeps working unchanged.crontab.txt+just install-crontab. Commits the existing schedule to the repo and adds a recipe to install it.Open question: host cron vs cron-in-docker
What's in this PR is host cron —
crontab.txtis installed onto the VPS viajust install-crontaband the system cron daemon still runs the schedule. It only version-controls the entries.After committing this, we agreed the better shape is cron in docker — either a dedicated
schedulerservice runningcron -f(mirrors brainspread'sbrainspread-scheduler-1) or cron inside the existing web container. That's not in this PR and would be a separate change that dropscrontab.txt/install-crontaband adds the chosen approach.Two ways to land this:
Either is fine — flagging so you can decide.
What changed (4 files)
app/plex/commands.py— async refactor ofSyncWithPlexCommand+ optionalsession=onEnrichMovieActorsCommand.executebin/dcp-django-admin.sh—compose execpreferred overcompose run, non-TTY-safe, reads env from.envcrontab.txt— new, byte-identical to what's currently installed on the VPSjustfile— addsinstall-crontabrecipeDeploy steps
The auto-deploy added in #34 should run this entire PR on merge. After it lands:
Confirm services are healthy:
docker ps --format 'table {{.Names}}\t{{.Status}}'Diagnose enrichment backfill scope. The OOM kills mid-sync caused recent movies to never get enriched — the next sync's
latest_movieearly-exit then skips them permanently:Backfill if the percentage is low:
docker compose exec -T web python manage.py enrich_actors(Optional, only if keeping the host-cron pieces) Install the version-controlled crontab — functionally a no-op since entries are byte-identical, but moves source-of-truth to the repo:
cd /root/oscarr-stuff/oscarr/packages/django-app just install-crontabTest plan
Lint and TestpassesDeploy to Productionfires automatically and SSHes into the VPS successfullyoscarr-web-1,oscarr-bot-1,oscarr-db-1allUpjust sync-with-plexdoes not spawn a new container (verify viadocker events --filter event=createduring a sync)*/10 * * * *boundary completes without prompt-hang and without OOMmanage.py enrich_actorsstill works (signature compat for the manual backfill)https://claude.ai/code/session_01RJrZb4X5Ywuzq2SjeFXgN1