Phoenix deployen, wenn die Job-Queue schon im Release steckt
Die meisten Frameworks brauchen einen zweiten deploybaren Prozess, nur um Hintergrundjobs laufen zu lassen — einen Worker-Dyno, einen separaten Container, etwas, das mit dem Build der Web-App synchron gehalten werden muss. Phoenix meistens nicht, weil Oban als Teil desselben OTP-Supervision-Trees läuft wie der Web-Endpoint selbst: Der Job-Runner ist keine zweite App, er lebt bereits in dem Moment, in dem web bootet.
Was aus mix.exs gelesen wird
- Datenspeicher werden anhand von Abhängigkeiten erkannt, nicht doppelt deklariert:
ecto_sql/postgrexprovisioniert Postgres,ecto_ch/chprovisioniert ClickHouse,redixprovisioniert Redis. SECRET_KEY_BASEwird einmalig generiert, du musst ihn nicht selbst erzeugen und speichern.MIX_ENV=produndPHX_SERVER=truewerden automatisch gesetzt — die zwei Umgebungsflags, die ein kompiliertes Phoenix-Release tatsächlich braucht, um Traffic zu bedienen statt untätig zu bleiben.
railyard create my-app https://github.com/me/my-app --addons postgres
oder dieselbe Git-URL über das Dashboard, sobald GitHub verbunden ist.
Der Teil, der bei kompilierten Releases wirklich anders ist
Ein kompiliertes Elixir-Release hat zur Laufzeit kein mix — der Migrationsbefehl, der in der Entwicklung funktioniert (mix ecto.migrate), existiert in dem Artefakt, das tatsächlich ausgeliefert wird, nicht. Railyard findet, wo das Release seinen eigenen Migrator ablegt, und führt diesen stattdessen aus (bin/migrate, falls das Release einen definiert, sonst bin/<app> eval), und mix phx.server wird genauso zu bin/<app> start. Dieser Unterschied — Dev-Befehl versus das, was das kompilierte Release tatsächlich bereitstellt — ist das mit Abstand häufigste Problem bei einem ersten Elixir-Deploy auf jeder Plattform, und er wird behandelt, bevor die erste Migration überhaupt läuft.
Falls sich ein dedizierter Worker-Knoten tatsächlich lohnt
Oban braucht für die meisten Apps keinen zweiten Prozess — aber falls das Job-Volumen so hoch ist, dass eine langsame Queue anfangen könnte, Web-Requests auszuhungern, ist das Aufspalten auf einen eigenen Knoten immer noch eine Ein-Zeilen-Ergänzung, keine Architekturänderung:
web: bin/my_app start
worker: bin/my_app eval "MyApp.Release.worker()"
railyard scale my-app worker=2
Dasselbe Release, derselbe Build, nur anders gestartet — hinzufügen oder bearbeiten über den Workers-Tab, ohne Änderung am Repo.
Config und Secrets
Alles, was config/runtime.exs mit System.get_env/2 liest — BASE_URL, HTTP_PORT, LISTEN_IP, DATABASE_URL, CLICKHOUSE_DATABASE_URL und alles andere — ist eine einfache Variable unter Variables, oder gesetzt via railyard env:set my-app KEY=VALUE, nie fest in das kompilierte Release gebacken. Dasselbe Release läuft unverändert von Staging bis Produktion.
Vollständige Referenz: Phoenix- und Elixir-Docs, Worker und geplante Jobs.