Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Integration with your Elixir/Phoenix app - demo

integration_with_elixir_app.livemd

Integration with your Elixir/Phoenix app - demo

Mix.install([
  {:kino, "~> 0.13.0"}
])

Section

livebook_app_node = node()
require Kino.RPC
node = :"phoenix_app@127.0.0.1"
Node.set_cookie(node, :secret)
phoenix_app_node = Kino.RPC.eval_string(node, ~S"node()", file: __ENV__.file)
Kino.Markdown.new("""
```mermaid
flowchart LR

    subgraph "&nbsp&nbsp node: #{livebook_app_node} &nbsp&nbsp"
    lbapp[Livebook app]
    end

    subgraph "&nbsp&nbsp node: #{phoenix_app_node} &nbsp&nbsp"
    phxapp[Phoenix app]
    end

    lbapp-.Erlang distributed.-phxapp
```
""")
import Kino.Shorts
cache_name = :my_cache
cache_key = read_text("Cache key")

if cache_key == "" do
  Kino.interrupt!(:normal, "👆 Fill in the inputs")
end
require Kino.RPC
node = :"phoenix_app@127.0.0.1"
Node.set_cookie(node, :secret)

ttl =
  Kino.RPC.eval_string(node, ~S"Cachex.ttl!(cache_name, cache_key)", file: __ENV__.file)
defmodule KinoCachex.TTL do
  def new(key, ttl) do
    Kino.HTML.new("""
    

The cache entry with key "#{key}" will expire in:

function formatDuration(seconds) { const days = Math.floor(seconds / (24 * 60 * 60)); seconds %= 24 * 60 * 60; const hours = Math.floor(seconds / (60 * 60)); seconds %= 60 * 60; const minutes = Math.floor(seconds / 60); seconds %= 60; const parts = []; if (days > 0) parts.push(`${days} day${days !== 1 ? 's' : ''}`); if (hours > 0) parts.push(`${hours} hour${hours !== 1 ? 's' : ''}`); if (minutes > 0) parts.push(`${minutes} minute${minutes !== 1 ? 's' : ''}`); if (seconds > 0 || parts.length === 0) parts.push(`${seconds} second${seconds !== 1 ? 's' : ''}`); if (parts.length > 1) { const lastPart = parts.pop(); return parts.join(', ') + ', and ' + lastPart; } else { return parts[0]; } } function updateDuration() { const spanElement = document.getElementById('ttl'); const ttlAt = spanElement.getAttribute('data-ttl-at'); const now = Math.floor(Date.now() / 1000); console.log(now); const timeUntilTtl = ttlAt - now; const formattedDuration = formatDuration(timeUntilTtl); spanElement.textContent = formattedDuration; } updateDuration(); setInterval(updateDuration, 1000); """
) end defp ttl_at(ttl) do DateTime.utc_now() |> DateTime.add(ttl, :millisecond) |> DateTime.to_unix() end end
ttl_frame = frame(placeholder: false)
Kino.Frame.render(ttl_frame, KinoCachex.TTL.new(cache_key, ttl))
ttl_frame
text("Do you want to delete that cache entry now?") |> Kino.render()

clear_cache = read_select("", [{"", ""}, {true, "yes"}, {false, "no"}])

if clear_cache == "" do
  Kino.interrupt!(:normal, "👆 Fill in the inputs")
end
require Kino.RPC
node = :"phoenix_app@127.0.0.1"
Node.set_cookie(node, :secret)

Kino.RPC.eval_string(
  node,
  ~S"""
  if clear_cache == true do
    Cachex.del!(cache_name, cache_key)
  end
  """,
  file: __ENV__.file
)
Kino.Frame.clear(ttl_frame)
text("Finished ✅")