Web apps rarely run in a straight line.
Uploads, emails, image processing, external API calls, PDF generation — some tasks take time.
In a synchronous world, that means waiting.
In a reactive world, frustration.
In a Phoenix LiveView world? Opportunity.
When you pair LiveView (stateful UI) with Oban (best‑in‑class Elixir job processor), you get live feedback loops that keep users informed without blocking the socket.
1. Enqueue the Work, Instantly
User submits a video to transcode:
# live_view.ex
def handle_event("submit_video", %{"id" => id}, socket) do
# Enqueue the heavy work
%{video_id: id}
|> Oban.insert(VideoTranscoder)
# Immediate UI feedback
{:noreply, assign(socket, status: :processing)}
end
-
Oban.insert/1
is non‑blocking (≈ 1 ms). - LiveView updates the UI right away: shows Processing….
2. Subscribing to Job Updates
In mount/3
, subscribe the LiveView to a PubSub topic:
def mount(%{"id" => id}, _session, socket) do
topic = "video:#{id}"
Phoenix.PubSub.subscribe(MyApp.PubSub, topic)
{:ok, assign(socket, status: :queued, topic: topic)}
end
3. Worker Broadcasts Progress
defmodule VideoTranscoder do
use Oban.Worker, queue: :media
@impl true
def perform(%Oban.Job{args: %{"video_id" => id}}) do
# …transcode logic…
Phoenix.PubSub.broadcast(MyApp.PubSub, "video:#{id}", {:transcode_finished, id})
:ok
end
end
4. LiveView Reacts in Real Time
def handle_info({:transcode_finished, _id}, socket) do
{:noreply, assign(socket, status: :done)}
end
Result: the UI flips from Processing… to Completed the moment the job ends — no polling.
5. Handling Failures & Retries
Oban retries jobs automatically with back‑off.
Expose that state to users:
def handle_info({:transcode_failed, reason}, socket) do
{:noreply, assign(socket, status: {:error, reason})}
end
Your interface can now show:
- “Retrying in 30 s…”
- “Click to resubmit”
- Error details for debugging
6. Live Dashboards, Scheduled Jobs, and More
- Live dashboards: Stream Oban job stats into a LiveView admin panel.
-
Scheduled work:
scheduled_at: DateTime.add(now, 60)
to run jobs later. - Cancellation: Push a button → broadcast “cancel” → Oban safely discards the job.
Everything remains reactive — even future tasks.
7. Why This Works
Layer | Responsibility |
---|---|
LiveView | Render & re‑render state |
Oban | Run & track background work |
PubSub | Bridge updates to the UI |
They’re independent, yet perfectly aligned:
- LiveView never blocks.
- Oban scales across nodes (Postgres advisory locks).
- PubSub delivers instant status updates.
8. UX That Feels Alive
Users never ask “Is this working?” — they see it working:
- Progress bars instead of spinners
- Real‑time status instead of blind polling
- Retry indicators instead of silent failure
You’re not faking immediacy; you’re rendering actual state as it evolves.
Ready to Master Phoenix LiveView?
Grab the free PDF Phoenix LiveView: The Pro’s Guide to Scalable Interfaces and UI Patterns
- Integrating LiveView with background jobs
- Distributed systems patterns
- Production‑grade UI strategies
Save weeks of guesswork and unlock Phoenix’s full potential!