Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ jobs:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "26.0.2"
gleam-version: "1.4.1"
otp-version: "28"
gleam-version: "1.16.0"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
Expand Down
2 changes: 1 addition & 1 deletion demo/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/gleam-lang/gleam:v1.6.3-erlang-alpine
FROM ghcr.io/gleam-lang/gleam:v1.16.0-erlang-alpine

COPY gleam.toml manifest.toml /build/

Expand Down
16 changes: 9 additions & 7 deletions demo/gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ version = "1.0.0"
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
pprint = ">= 1.0.3 and < 2.0.0"
barnacle = ">= 1.0.0 and < 2.0.0"
gleam_otp = ">= 0.12.1 and < 1.0.0"
gleam_erlang = ">= 0.28.0 and < 1.0.0"
mist = ">= 3.0.0 and < 4.0.0"
lustre = ">= 4.5.1 and < 5.0.0"
gleam_json = ">= 1.0.1 and < 2.0.0"
gleam_http = ">= 3.7.0 and < 4.0.0"
# barnacle = ">= 1.0.0 and < 2.0.0"
barnacle = { path = "../" }
gleam_otp = ">= 1.0.0 and < 2.0.0"
gleam_erlang = ">= 1.0.0 and < 2.0.0"
mist = ">= 6.0.0 and < 7.0.0"
lustre = ">= 5.0.0 and < 6.0.0"
gleam_json = ">= 3.0.0 and < 4.0.0"
gleam_http = ">= 4.0.0 and < 5.0.0"
argv = ">= 1.0.2 and < 2.0.0"
youid = ">= 1.2.0 and < 2.0.0"
envoy = ">= 1.2.0 and < 2.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
55 changes: 28 additions & 27 deletions demo/manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,40 @@

packages = [
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
{ name = "barnacle", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "barnacle", source = "hex", outer_checksum = "C081C978FB63AC96EAC90A8336575F3958DF94B50EE840779B88E8A256B98F48" },
{ name = "birl", version = "1.7.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "5C66647D62BCB11FE327E7A6024907C4A17954EF22865FE0940B54A852446D01" },
{ name = "glam", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "66EC3BCD632E51EED029678F8DF419659C1E57B1A93D874C5131FE220DFAD2B2" },
{ name = "gleam_crypto", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "8AE56026B3E05EBB1F076778478A762E9EB62B31AEEB4285755452F397029D22" },
{ name = "gleam_erlang", version = "0.28.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "BE551521F708DCE5CB954AFBBDF08519C1C44986521FD40753608825F48FFA9E" },
{ name = "gleam_http", version = "3.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "EA66440C2269F7CED0F6845E5BD0DB68095775D627FA709A841CA78A398D6D56" },
{ name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" },
{ name = "gleam_otp", version = "0.12.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "BFACC1513410DF5A1617169A9CD7EA334973AC71D860A17574BA7B2EADD89A6F" },
{ name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" },
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
{ name = "glisten", version = "6.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging", "telemetry"], otp_app = "glisten", source = "hex", outer_checksum = "912132751031473CB38F454120124FFC96AF6B0EA33D92C9C90DB16327A2A972" },
{ name = "gramps", version = "2.0.3", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "3CCAA6E081225180D95C79679D383BBF51C8D1FDC1B84DA1DA444F628C373793" },
{ name = "barnacle", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], source = "local", path = ".." },
{ name = "envoy", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "9C6FBB6BFA02A52798BEEC5977A738CAD6E4A057F4B67FD0C8061AD2502C191A" },
{ name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" },
{ name = "glam", version = "2.0.4", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "48A043A12091F93D911C316DD8F7FFD03CD9FF6F50848FC56E359D3C168DF0FA" },
{ name = "gleam_crypto", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "2DE9E4EF53CF6FEE049D4F765731F7178F7A11AEFAE00EEE63BF7536B354AD3F" },
{ name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
{ name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" },
{ name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
{ name = "gleam_otp", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "BA6A294E295E428EC1562DC1C11EA7530DCB981E8359134BEABC8493B7B2258E" },
{ name = "gleam_stdlib", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "960090C2FB391784BB34267B099DC9315CC1B1F6013E7415BC763CEF1905D7D3" },
{ name = "gleam_time", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "533D8723774D61AD4998324F5DD1DABDCDBFABAFB9E87CB5D03C6955448FC97D" },
{ name = "gleeunit", version = "1.10.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "254B697FE72EEAD7BF82E941723918E421317813AC49923EE76A18C788C61E72" },
{ name = "glisten", version = "9.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging"], otp_app = "glisten", source = "hex", outer_checksum = "7795AA50830656F3A0316A6B26595F893C83272DA901B3405E31339CAA31A10B" },
{ name = "gramps", version = "6.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "D55636072DEE173F6586A5679D3C02EC7A0DE3F8646B78C351B72908FF223DF7" },
{ name = "houdini", version = "1.2.1", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "6F8AC2F12974567FB744BEA66AC93CEB76AAEA19AD28564623F76CDA9BC26A85" },
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
{ name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" },
{ name = "lustre", version = "4.5.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib"], otp_app = "lustre", source = "hex", outer_checksum = "B592DA442F6577143CAFA35D4506DB2018DAEED9C707A921E33559E09F001DF1" },
{ name = "mist", version = "3.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "CDA1A74E768419235E16886463EC4722EFF4AB3F8D820A76EAD45D7C167D7282" },
{ name = "pprint", version = "1.0.3", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "76BBB92E23D12D954BD452686543F29EDE8EBEBB7FC0ACCBCA66EEF276EC3A06" },
{ name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" },
{ name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" },
{ name = "thoas", version = "1.2.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "E38697EDFFD6E91BD12CEA41B155115282630075C2A727E7A6B2947F5408B86A" },
{ name = "youid", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_stdlib"], otp_app = "youid", source = "hex", outer_checksum = "EF0F693004E221155EE5909C6D3C945DD14F7117DBA882887CF5F45BE399B8CA" },
{ name = "logging", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "BC5F18CE5DD9686100229FE5409BDC3DD5C46D5A7DF2F804AD2D8F0DD6C5060E" },
{ name = "lustre", version = "5.6.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib", "houdini"], otp_app = "lustre", source = "hex", outer_checksum = "EE558CD4DB9F09FCC16417ADF0183A3C2DAC3E4B21ED3AC0CAE859792AB810CA" },
{ name = "mist", version = "6.0.3", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "1B07F321D5FA0CB162D81496F2DE96AEB6EF8980F4F38230A4CC3F849497E020" },
{ name = "pprint", version = "1.0.6", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "4E9B34AE03B2E81D60F230B9BAF1792BE1AC37AFB5564B8DEBEE56BAEC866B7D" },
{ name = "youid", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_stdlib", "gleam_time"], otp_app = "youid", source = "hex", outer_checksum = "7A3ABA44B1B38BC2BDCB5474C5317AA372BE58DFBC649815EE08B03526DDA18D" },
]

[requirements]
argv = { version = ">= 1.0.2 and < 2.0.0" }
barnacle = { version = ">= 1.0.0 and < 2.0.0" }
gleam_erlang = { version = ">= 0.28.0 and < 1.0.0" }
gleam_http = { version = ">= 3.7.0 and < 4.0.0" }
gleam_json = { version = ">= 1.0.1 and < 2.0.0" }
gleam_otp = { version = ">= 0.12.1 and < 1.0.0" }
barnacle = { path = "../" }
envoy = { version = ">= 1.2.0 and < 2.0.0" }
gleam_erlang = { version = ">= 1.0.0 and < 2.0.0" }
gleam_http = { version = ">= 4.0.0 and < 5.0.0" }
gleam_json = { version = ">= 3.0.0 and < 4.0.0" }
gleam_otp = { version = ">= 1.0.0 and < 2.0.0" }
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
lustre = { version = ">= 4.5.1 and < 5.0.0" }
mist = { version = ">= 3.0.0 and < 4.0.0" }
lustre = { version = ">= 5.0.0 and < 6.0.0" }
mist = { version = ">= 6.0.0 and < 7.0.0" }
pprint = { version = ">= 1.0.3 and < 2.0.0" }
youid = { version = ">= 1.2.0 and < 2.0.0" }
92 changes: 48 additions & 44 deletions demo/src/barnacle_demo.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import argv
import barnacle
import barnacle_demo/node_list
import gleam/bytes_builder
import gleam/erlang
import envoy
import gleam/bytes_tree
import gleam/erlang/application
import gleam/erlang/atom
import gleam/erlang/node
import gleam/erlang/os
import gleam/erlang/process.{type Selector, type Subject}
import gleam/http/request.{type Request}
import gleam/http/response.{type Response}
Expand All @@ -18,7 +18,6 @@ import gleam/io
import gleam/json
import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/otp/actor
import gleam/result
import gleam/string
import lustre
Expand Down Expand Up @@ -56,18 +55,18 @@ pub fn main() {
let listener = process.new_subject()

// Get the Fly app name from the environment
let assert Ok(app_name) = os.get_env("FLY_APP_NAME")
let assert Ok(app_name) = envoy.get("FLY_APP_NAME")

let barnacle =
// Use internal DNS to connect to the nodes
barnacle.dns(basename, app_name <> ".internal")
barnacle.dns(basename, app_name <> ".internal", None)
|> barnacle.with_listener(listener)
|> barnacle.with_poll_interval(barnacle_poll_interval)

let assert Ok(barnacle_subject) = barnacle.start(barnacle)

let app = node_list.app()
let assert Ok(node_list) = lustre.start_actor(app, barnacle_subject)
let assert Ok(node_list) =
lustre.start_server_component(node_list.component(), barnacle_subject.data)

let assert Ok(_) = run_server(port, node_list)
listen_and_publish(listener, node_list)
Expand All @@ -76,11 +75,11 @@ pub fn main() {
// ----- Server component updater ----- //

type NodeList =
Subject(lustre.Action(node_list.Msg, lustre.ServerComponent))
lustre.Runtime(node_list.Msg)

fn listen_and_publish(
listener: Subject(barnacle.BarnacleResponse(a)),
node_list: NodeList,
node_list: lustre.Runtime(_),
) {
case process.receive(listener, listener_poll_interval) {
Ok(barnacle.RefreshResponse(Ok(nodes))) -> {
Expand All @@ -93,12 +92,15 @@ fn listen_and_publish(
_ -> Nil
}

process.send(
lustre.send(
node_list,
lustre.dispatch(node_list.UpdateNodes(
[node.self(), ..node.visible()]
|> io.debug
|> list.map(fn(node) { node |> node.to_atom |> atom.to_string })
|> fn(nodes) {
nodes |> string.inspect |> io.println
nodes
}
|> list.map(fn(node) { node |> node.name |> atom.to_string })
|> list.sort(string.compare),
)),
)
Expand All @@ -108,7 +110,7 @@ fn listen_and_publish(

// ----- Mist server ----- //

fn run_server(port: Int, node_list: NodeList) {
fn run_server(port: Int, node_list: lustre.Runtime(_)) {
fn(req: Request(Connection)) -> Response(ResponseData) {
case request.path_segments(req) {
["node_list"] ->
Expand All @@ -120,7 +122,7 @@ fn run_server(port: Int, node_list: NodeList) {
)

["lustre-server-component.mjs"] -> {
let assert Ok(priv) = erlang.priv_directory("lustre")
let assert Ok(priv) = application.priv_directory("lustre")
let path = priv <> "/static/lustre-server-component.mjs"

mist.send_file(path, offset: 0, limit: None)
Expand All @@ -131,7 +133,7 @@ fn run_server(port: Int, node_list: NodeList) {
})
|> result.lazy_unwrap(fn() {
response.new(404)
|> response.set_body(mist.Bytes(bytes_builder.new()))
|> response.set_body(mist.Bytes(bytes_tree.new()))
})
}

Expand All @@ -158,67 +160,69 @@ fn run_server(port: Int, node_list: NodeList) {
),
]),
])
|> element.to_document_string_builder
|> bytes_builder.from_string_builder
|> element.to_document_string()
|> bytes_tree.from_string()
|> mist.Bytes,
)
}
}
|> mist.new
|> mist.bind("0.0.0.0")
|> mist.port(port)
|> mist.start_http
|> mist.start()
}

type State =
#(String, NodeList)
type State {
State(id: String, component: NodeList)
}

fn socket_init(
_conn: WebsocketConnection,
node_list: NodeList,
) -> #(State, Option(Selector(lustre.Patch(node_list.Msg)))) {
runtime: lustre.Runtime(_),
) -> #(State, Option(Selector(server_component.ClientMessage(node_list.Msg)))) {
let self = process.new_subject()
let id = uuid.v4() |> uuid.to_string

process.send(node_list, server_component.subscribe(id, process.send(self, _)))
let selector =
process.new_selector()
|> process.select(self)

#(
#(id, node_list),
Some(process.selecting(process.new_selector(), self, fn(a) { a })),
)
server_component.register_subject(self)
|> lustre.send(to: runtime)

#(State(id, runtime), Some(selector))
}

fn socket_update(
state: State,
msg: WebsocketMessage(server_component.ClientMessage(node_list.Msg)),
conn: WebsocketConnection,
msg: WebsocketMessage(lustre.Patch(node_list.Msg)),
) {
) -> mist.Next(State, server_component.ClientMessage(node_list.Msg)) {
case msg {
mist.Text(json) -> {
let action = json.decode(json, server_component.decode_action)
let action = json.parse(json, server_component.runtime_message_decoder())

case action {
Ok(action) -> process.send(state.1, action)
Ok(action) -> lustre.send(state.component, action)
Error(_) -> Nil
}

actor.continue(state)
mist.continue(state)
}

mist.Binary(_) -> actor.continue(state)
mist.Custom(patch) -> {
let assert Ok(_) =
patch
|> server_component.encode_patch
|> json.to_string
|> mist.send_text_frame(conn, _)
mist.Binary(_) -> mist.continue(state)
mist.Custom(client_message) -> {
let json = server_component.client_message_to_json(client_message)

let assert Ok(_) = mist.send_text_frame(conn, json.to_string(json))

actor.continue(state)
mist.continue(state)
}
mist.Closed | mist.Shutdown -> actor.Stop(process.Normal)
mist.Closed | mist.Shutdown -> mist.stop()
}
}

fn socket_close(state: State) {
process.send(state.1, server_component.unsubscribe(state.0))
fn socket_close(state: State) -> Nil {
lustre.shutdown()
|> lustre.send(to: state.component)
}
Loading