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 "   node: #{livebook_app_node}   "
lbapp[Livebook app]
end
subgraph "   node: #{phoenix_app_node}   "
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 ✅")