Skip to content

Instantly share code, notes, and snippets.

@nmk
Last active March 3, 2023 11:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nmk/51c582bce19b8314b4e4b62c71e83cb3 to your computer and use it in GitHub Desktop.
Save nmk/51c582bce19b8314b4e4b62c71e83cb3 to your computer and use it in GitHub Desktop.
Phoenix disappearing streams
Application.put_env(:sample, SamplePhoenix.Endpoint,
http: [ip: {127, 0, 0, 1}, port: 5001],
server: true,
live_view: [signing_salt: "aaaaaaaa"],
secret_key_base: String.duplicate("a", 64)
)
Mix.install([
{:plug_cowboy, "~> 2.5"},
{:jason, "~> 1.0"},
{:phoenix, "~> 1.7.0", override: true},
{:phoenix_live_view, "~> 0.18.16"}
])
defmodule SamplePhoenix.ErrorView do
def render(template, _), do: Phoenix.Controller.status_message_from_template(template)
end
defmodule SamplePhoenix.SampleLive do
use Phoenix.LiveView, layout: {__MODULE__, :live}
use Phoenix.VerifiedRoutes,
endpoint: SamplePhoenix.Endpoint,
router: SamplePhoenix.Router
def mount(_params, _session, socket) do
if connected?(socket), do: send(self(), {:load_external_data})
apples = Enum.map(Enum.take_random(1..10, 3), &%{id: &1, value: &1})
{:ok, stream(socket, :apples, apples)}
end
def render("live.html", assigns) do
~H"""
<script src="https://cdn.jsdelivr.net/npm/phoenix@1.7.0/priv/static/phoenix.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/phoenix_live_view@0.18.16/priv/static/phoenix_live_view.min.js"></script>
<script>
let liveSocket = new window.LiveView.LiveSocket("/live", window.Phoenix.Socket)
liveSocket.connect()
</script>
<style>
* { font-size: 1.1em; }
</style>
<%= @inner_content %>
"""
end
def render(assigns) do
~H"""
<h1>Streams Test</h1>
<.link navigate={~p"/"}>Navigate again</.link>
<p :if={assigns[:external_data]}><%= @external_data %></p>
<ul id="apples" phx-update="stream"><li :for={{dom_id, apple} <- @streams.apples} id={dom_id}>Apple: <%= apple.value %></li></ul>
"""
end
def handle_info({:load_external_data}, socket) do
Process.sleep(2000)
{:noreply, assign(socket, :external_data, "External data.")}
end
end
defmodule Router do
use Phoenix.Router
import Phoenix.LiveView.Router
pipeline :browser do
plug(:accepts, ["html"])
end
scope "/", SamplePhoenix do
pipe_through(:browser)
live("/", SampleLive, :index)
end
end
defmodule SamplePhoenix.Endpoint do
use Phoenix.Endpoint, otp_app: :sample
socket("/live", Phoenix.LiveView.Socket)
plug(Router)
end
{:ok, _} = Supervisor.start_link([SamplePhoenix.Endpoint], strategy: :one_for_one)
Process.sleep(:infinity)
Application.put_env(:sample, SamplePhoenix.Endpoint,
http: [ip: {127, 0, 0, 1}, port: 5001],
server: true,
live_view: [signing_salt: "aaaaaaaa"],
secret_key_base: String.duplicate("a", 64)
)
Mix.install([
{:plug_cowboy, "~> 2.5"},
{:jason, "~> 1.0"},
{:phoenix, "~> 1.7.0", override: true},
{:phoenix_live_view, "~> 0.18.16"}
])
defmodule SamplePhoenix.ErrorView do
def render(template, _), do: Phoenix.Controller.status_message_from_template(template)
end
defmodule SamplePhoenix.SampleLive do
use Phoenix.LiveView, layout: {__MODULE__, :live}
use Phoenix.VerifiedRoutes,
endpoint: SamplePhoenix.Endpoint,
router: SamplePhoenix.Router
def mount(_params, _session, socket) do
if connected?(socket), do: send(self(), {:load_external_data})
apples = Enum.map(Enum.take_random(1..10, 3), &%{id: &1, value: &1})
{:ok, stream(socket, :apples, apples)}
end
def render("live.html", assigns) do
~H"""
<script src="https://cdn.jsdelivr.net/npm/phoenix@1.7.0/priv/static/phoenix.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/phoenix_live_view@0.18.16/priv/static/phoenix_live_view.min.js"></script>
<script>
let liveSocket = new window.LiveView.LiveSocket("/live", window.Phoenix.Socket)
liveSocket.connect()
</script>
<style>
* { font-size: 1.1em; }
</style>
<%= @inner_content %>
"""
end
def render(assigns) do
~H"""
<h1>Streams Test</h1>
<.link navigate={~p"/"}>Navigate again</.link>
<p :if={assigns[:external_data]}><%= @external_data %></p>
<ul id="apples" phx-update="stream">
<li :for={{dom_id, apple} <- @streams.apples} id={dom_id}>Apple: <%= apple.value %></li>
</ul>
"""
end
def handle_info({:load_external_data}, socket) do
Process.sleep(2000)
{:noreply, assign(socket, :external_data, "External data.")}
end
end
defmodule Router do
use Phoenix.Router
import Phoenix.LiveView.Router
pipeline :browser do
plug(:accepts, ["html"])
end
scope "/", SamplePhoenix do
pipe_through(:browser)
live("/", SampleLive, :index)
end
end
defmodule SamplePhoenix.Endpoint do
use Phoenix.Endpoint, otp_app: :sample
socket("/live", Phoenix.LiveView.Socket)
plug(Router)
end
{:ok, _} = Supervisor.start_link([SamplePhoenix.Endpoint], strategy: :one_for_one)
Process.sleep(:infinity)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment