Build a live poll
This tutorial teaches beryl by building one app: a live poll. If you want a
shorter path, start with the Quick Start. All prose and code
excerpts come from the runnable
examples/live_poll/
project. beryl is pre-1.0. Expect the API to change.
Chapters
Section titled “Chapters”- The Elm architecture, without a DOM
- One update function, many socket events
- Typed messages from the rest of your Gleam system
- Composition: raw dispatch and
beryl/channel - Where the analogy ends
- Supervising beryl
You can read each chapter on its own. The checkpoints build on each other. They start with a read-only poll and end with a supervised channel system.
Runnable checkpoints
Section titled “Runnable checkpoints”Run each command from the repository root:
| Chapter | Command | URL |
|---|---|---|
| 1 | cd examples/live_poll && gleam run -m live_poll/step_01 | http://localhost:8101 |
| 2 | cd examples/live_poll && gleam run -m live_poll/step_02 | http://localhost:8102 |
| 3 | cd examples/live_poll && gleam run -m live_poll/step_03 | http://localhost:8103 |
| 4 | cd examples/live_poll && gleam run -m live_poll/step_04 | http://localhost:8104 |
| 5 | cd examples/live_poll && gleam run -m live_poll/step_05 | http://localhost:8105 |
| 6 | cd examples/live_poll && gleam run -m live_poll/step_05 | http://localhost:8105 |
Stop a checkpoint with Ctrl-C before you start the next one. The browser client loads Phoenix JavaScript 1.7.20 from unpkg, so the first page load needs internet access. The Gleam server and the beryl runtime run on your machine.
Files used by every chapter
Section titled “Files used by every chapter”The five step_0N.gleam files are short entry modules. Each one picks a
configuration and starts the shared modules:
raw.gleamhas the rawinit,Model,Message, andupdatefunction used by steps 1 through 3.channel_handler.gleamhas the twochannel.Handlervalues used by steps 4 and 5.poll.gleamdefines the poll types and turns clientDynamicpayloads into poll commands.store.gleamkeeps poll state in a Gleam OTP actor.timer.gleamruns delayed callbacks from its own actor.server.gleamstarts the beryl child specification and the Mist transport, serves the browser client, and can serve/healthz.test/live_poll_test.gleamtests the poll types and the protocol decoder.
Read each step module together with the shared files. A step file shows which behavior is on. It does not repeat the runtime, poll, or browser code.
Terms used in this tutorial
Section titled “Terms used in this tutorial”The tutorial uses these terms, and keeps them separate:
- A socket is one client connection that the beryl runtime knows about.
- A topic is a string that a socket subscribes to, such as
poll:demo. - Raw dispatch is the core API. Your app defines a Model and an update
function. The update function receives a
socket.Input, and returns asocket.Nextwith a list ofsocket.Effectvalues. Asocket.Senderlets other code send typed messages to one socket. - A channel is one accepted topic on one socket, managed by
beryl/channel. A handler matches a topic pattern and builds that channel: its private state, its callbacks, and its typed info messages. - A channel callback returns a list of actions. Each action applies to the callback's own topic.
- The runtime has one router actor and one actor for each connected socket. The socket actor holds the model and runs effects. The router keeps the socket index and sends broadcasts to subscribers.
- A Gleam OTP
process.Subjectis a typed address for a process mailbox. A berylsocket.Senderis narrower. It delivers typedInfoonly to the socket that owns it. After the socket disconnects, the runtime drops the message.
Do not use Subject, Sender, socket, topic, channel, or handler in
place of one another. Each term names a different part of the system.
Raw dispatch is beryl's core, and the clearest way to learn it. For apps with
many channels, or apps shaped like Phoenix, use beryl/channel.
