Dala.Dist (dala v0.0.1)

Copy Markdown View Source

Platform-aware Erlang distribution startup.

On iOS, distribution is started at BEAM launch via flags in dala_beam.m (-name dala_demo@127.0.0.1), so nothing extra is needed here.

On Android, starting distribution at BEAM launch races with Android's hwui thread pool initialization (~125ms window), corrupting an internal mutex and causing a SIGABRT. The fix is to defer Node.start/2 until after the UI has fully settled.

Additionally, mix dala.connect runs adb reverse tcp:4369 tcp:4369 to tunnel Mac EPMD into the device. OTP's Node.start/2 would ordinarily spawn a local epmd daemon that also tries to bind port 4369 — causing a port conflict and crash. The fix: set start_epmd: false and wait for the ADB-tunnelled EPMD to be reachable before calling Node.start/2. If the tunnel is not up within 10s (standalone launch, no mix dala.connect), distribution is skipped gracefully.

Usage (in your app's start/0)

# ⚠️ NEVER use hardcoded cookies in production!
# Generate a secure cookie per app and store it securely.
cookie = Dala.Dist.cookie_from_env("MY_APP_DIST_COOKIE", "my_app")
Dala.Dist.ensure_started(node: :"my_app@127.0.0.1", cookie: cookie)

Options:

  • :node — node name atom, e.g. :"dala_demo@127.0.0.1" (required on Android)
  • :cookie — cookie atom (required on Android) — use cookie_from_env/2
  • :delay — ms to wait before starting dist on Android (default: 3_000)

Summary

Functions

Generate a secure distribution cookie from environment or derive from app name.

Ensure Erlang distribution is running for the current platform.

Stop Erlang distribution and shut down EPMD.

Functions

ensure_started(opts \\ [])

@spec ensure_started(keyword()) :: :ok

Ensure Erlang distribution is running for the current platform.

  • iOS: no-op (dist already started via BEAM args in dala_beam.m).
  • Android: spawns a process that sleeps for :delay ms then calls Node.start/2 + Node.set_cookie/1. Pins the dist port to :dist_port (default 9100) so dev_connect.sh knows which port to forward.

Options:

  • :node — base node name atom (required on Android)
  • :cookie — cookie atom (required on Android)
  • :delay — ms to wait before starting dist (default: 3_000)
  • :dist_port — Erlang dist listen port (default: 9100)

Per-device node names (Android)

Mac's EPMD only allows one registration per name. Two phones running the same app with the same hardcoded :node collide — the second to start gets :nodistribution and silently runs without dist. To keep two or more devices distinguishable, set the dala_NODE_SUFFIX env var (the Android shell launcher reads dala_node_suffix from the launch intent extras and exports it). When present, the resolved node becomes <base_name>_<suffix>@<host> — e.g. test_nif_android_zy22cr@127.0.0.1.

Security notes

  • Never commit distribution cookies to source control.
  • Never use hardcoded atoms like :secret or :dala_secret in production.
  • Store cookies in environment variables or secure key storage.
  • Rotate cookies periodically using Node.set_cookie/1.
  • The Dala.Diag module is a permanent target if credentials leak — see Dala.Diag docs for mitigation strategies.

stop()

@spec stop() :: :ok

Stop Erlang distribution and shut down EPMD.

Disconnects all connected nodes, stops the distribution listener, and terminates the local EPMD daemon if one was started by this node.

Intended for use after an OTA update session or when forming a Dala.Cluster connection that should not persist. The app continues running normally after calling stop/0 — only remote connectivity is removed.

Returns :ok whether or not distribution was running.

# OTA update session
Dala.Dist.ensure_started(node: :"my_app@127.0.0.1", cookie: session_cookie)
Node.connect(update_server_node)
# ... receive BEAMs ...
Dala.Dist.stop()

# Dala.Cluster — rotate cookie between sessions
Node.set_cookie(new_session_cookie)   # no restart needed