diff --git a/gleam.toml b/gleam.toml index 28d4919..4b4a396 100644 --- a/gleam.toml +++ b/gleam.toml @@ -7,9 +7,9 @@ repository = { type = "github", user = "Pevensie", repo = "barnacle" } # links = [{ title = "Website", href = "" }] [dependencies] -gleam_stdlib = ">= 0.34.0 and < 2.0.0" -gleam_erlang = ">= 0.27.0 and < 1.0.0" -gleam_otp = ">= 0.12.1 and < 1.0.0" +gleam_stdlib = ">= 0.60.0 and < 2.0.0" +gleam_erlang = ">= 1.0.0 and < 2.0.0" +gleam_otp = ">= 1.0.0 and < 2.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index f00f8e5..4f93a0f 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,14 +2,14 @@ # You typically do not need to edit this file packages = [ - { name = "gleam_erlang", version = "0.34.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "0C38F2A128BAA0CEF17C3000BD2097EB80634E239CE31A86400C4416A5D0FDCC" }, - { name = "gleam_otp", version = "0.16.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "50DA1539FC8E8FA09924EB36A67A2BBB0AD6B27BCDED5A7EF627057CF69D035E" }, - { name = "gleam_stdlib", version = "0.58.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "091F2D2C4A3A4E2047986C47E2C2C9D728A4E068ABB31FDA17B0D347E6248467" }, - { name = "gleeunit", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "0E6C83834BA65EDCAAF4FE4FB94AC697D9262D83E6F58A750D63C9F6C8A9D9FF" }, + { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" }, + { 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 = "0.67.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "6CE3E4189A8B8EC2F73AB61A2FBDE49F159D6C9C61C49E3B3082E439F260D3D0" }, + { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" }, ] [requirements] -gleam_erlang = { version = ">= 0.27.0 and < 1.0.0" } -gleam_otp = { version = ">= 0.12.1 and < 1.0.0" } -gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } +gleam_erlang = { version = ">= 1.0.0 and < 2.0.0" } +gleam_otp = { version = ">= 1.0.0 and < 2.0.0" } +gleam_stdlib = { version = ">= 0.60.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } diff --git a/src/barnacle.gleam b/src/barnacle.gleam index a8942d6..699f664 100644 --- a/src/barnacle.gleam +++ b/src/barnacle.gleam @@ -3,11 +3,10 @@ import barnacle/local_epmd import gleam/erlang/atom import gleam/erlang/node import gleam/erlang/process.{type Subject} -import gleam/function import gleam/list import gleam/option.{type Option, None, Some} import gleam/otp/actor -import gleam/otp/supervisor +import gleam/otp/supervision import gleam/result import gleam/set import gleam/string @@ -18,7 +17,7 @@ import gleam/string /// strategy-specific functions. pub opaque type Barnacle(error) { Barnacle( - name: Option(atom.Atom), + name: Option(process.Name(Message(error))), strategy: Strategy(error), poll_interval: Int, listener: Option(Subject(BarnacleResponse(error))), @@ -35,8 +34,11 @@ fn default_barnacle() -> Barnacle(error) { } /// Give the barnacle actor process a custom name. -pub fn with_name(barnacle: Barnacle(error), name: String) -> Barnacle(error) { - Barnacle(..barnacle, name: Some(name |> atom.create_from_string)) +pub fn with_name( + barnacle: Barnacle(error), + name: process.Name(Message(error)), +) -> Barnacle(error) { + Barnacle(..barnacle, name: Some(name)) } /// Set the poll interval for the barnacle actor. Defaults to 5000ms. @@ -131,7 +133,7 @@ fn disconnect_node(node: atom.Atom) -> Result(node.Node, NodeDisconnectError) fn list_nodes() -> Result(List(atom.Atom), error) { [node.self(), ..node.visible()] - |> list.map(node.to_atom) + |> list.map(node.name) |> Ok } @@ -207,16 +209,9 @@ pub fn dns( ) -> Barnacle(dns.LookupError) { Barnacle( ..default_barnacle(), - strategy: Strategy( - ..default_strategy(), - discover_nodes: fn() { - dns.discover_nodes( - basename, - hostname_query, - option.unwrap(timeout, 5000), - ) - }, - ), + strategy: Strategy(..default_strategy(), discover_nodes: fn() { + dns.discover_nodes(basename, hostname_query, option.unwrap(timeout, 5000)) + }), ) } @@ -253,7 +248,7 @@ type State(error) { pub fn start(barnacle: Barnacle(error)) { barnacle |> spec(None) - |> actor.start_spec + |> actor.start } /// Create a child spec for your barnacle for use in a supervision tree. @@ -261,10 +256,10 @@ pub fn child_spec( barnacle: Barnacle(error), parent: Subject(Subject(Message(error))), ) { - supervisor.worker(fn(_) { + supervision.worker(fn() { barnacle |> spec(Some(parent)) - |> actor.start_spec + |> actor.start }) } @@ -282,18 +277,18 @@ pub fn run_once(barnacle: Barnacle(error)) { /// /// This will reset the poll timer. pub fn refresh(subject: Subject(Message(error)), timeout: Int) { - actor.call(subject, fn(subj) { Refresh(Some(subj)) }, timeout) + actor.call(subject, timeout, fn(subj) { Refresh(Some(subj)) }) } /// Pause a barnacle actor. Sending a [`refresh`](#refresh) will restart the actor. pub fn pause(subject: Subject(Message(error)), timeout: Int) { - actor.call(subject, fn(subj) { Pause(Some(subj)) }, timeout) + actor.call(subject, timeout, fn(subj) { Pause(Some(subj)) }) } /// Shutdown a barnacle actor. This will stop the actor, and stop any future /// refreshes. pub fn shutdown(subject: Subject(Message(error)), timeout: Int) { - actor.call(subject, fn(subj) { Shutdown(Some(subj)) }, timeout) + actor.call(subject, timeout, fn(subj) { Shutdown(Some(subj)) }) } /// The error type for a barnacle refresh. @@ -303,7 +298,7 @@ pub type RefreshError(error) { DisconnectError(List(#(atom.Atom, NodeDisconnectError))) } -fn handle_message(message: Message(error), state: State(error)) { +fn handle_message(state: State(error), message: Message(error)) { let State(self:, barnacle:, timer:) = state case message { Refresh(return) -> { @@ -327,7 +322,7 @@ fn handle_message(message: Message(error), state: State(error)) { cancel_timer(timer) send_response(return, Nil) send_response(barnacle.listener, ShutdownResponse(Nil)) - actor.Stop(process.Normal) + actor.stop() } } } @@ -336,22 +331,28 @@ fn spec( barnacle: Barnacle(error), parent: Option(Subject(Subject(Message(error)))), ) { - actor.Spec(init_timeout: 10_000, loop: handle_message, init: fn() { - option.map(barnacle.name, process.register(process.self(), _)) - let self = process.new_subject() + actor.new_with_initialiser(10_000, fn(self) { + use _ <- result.try( + barnacle.name + |> option.map(process.register(process.self(), _)) + |> option.unwrap(Ok(Nil)) + |> result.replace_error("Failed to register process"), + ) + let selector = process.new_selector() - |> process.selecting(self, function.identity) + |> process.select(self) option.map(parent, process.send(_, self)) let timer = process.send_after(self, barnacle.poll_interval, Refresh(None)) - actor.Ready( - selector: selector, - state: State(self:, barnacle:, timer: Some(timer)), - ) + actor.initialised(State(self:, barnacle:, timer: Some(timer))) + |> actor.selecting(selector) + |> actor.returning(self) + |> Ok }) + |> actor.on_message(handle_message) } fn send_response(maybe_client: Option(Subject(a)), response: a) -> Nil { @@ -375,7 +376,7 @@ fn refresh_nodes(barnacle: Barnacle(error)) -> RefreshResult(error) { |> result.map_error(StrategyError), ) - let self = node.self() |> node.to_atom + let self = node.self() |> node.name let available_nodes = available_nodes_list @@ -427,7 +428,7 @@ fn result_apply(results: List(Result(a, b))) -> Result(List(a), List(b)) { /// ``` pub fn get_node_basename(node: node.Node) -> Result(String, Nil) { node - |> node.to_atom + |> node.name |> atom.to_string |> string.split_once("@") |> result.map(fn(tuple) { tuple.0 }) diff --git a/src/barnacle/dns.gleam b/src/barnacle/dns.gleam index 31dc8a6..5a275d8 100644 --- a/src/barnacle/dns.gleam +++ b/src/barnacle/dns.gleam @@ -99,7 +99,7 @@ pub fn discover_nodes( ip_addresses |> list.map(fn(ip) { let ip_string = format_ip_address(ip) - { basename <> "@" <> ip_string } |> atom.create_from_string + { basename <> "@" <> ip_string } |> atom.create }) |> Ok } diff --git a/src/barnacle/local_epmd.gleam b/src/barnacle/local_epmd.gleam index 476c514..4f428e8 100644 --- a/src/barnacle/local_epmd.gleam +++ b/src/barnacle/local_epmd.gleam @@ -10,7 +10,7 @@ fn list_local_nodes() -> Result(List(String), Nil) fn get_hostname() -> String { let host = node.self() - |> node.to_atom + |> node.name |> atom.to_string let assert [_, hostname] = string.split(host, "@") @@ -22,7 +22,5 @@ fn get_hostname() -> String { pub fn discover_nodes() -> Result(List(atom.Atom), Nil) { let hostname = get_hostname() list_local_nodes() - |> result.map(list.map(_, fn(n) { - { n <> "@" <> hostname } |> atom.create_from_string - })) + |> result.map(list.map(_, fn(n) { { n <> "@" <> hostname } |> atom.create })) }