Skip to content
Closed
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
6 changes: 3 additions & 3 deletions gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
14 changes: 7 additions & 7 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
69 changes: 35 additions & 34 deletions src/barnacle.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))),
Expand All @@ -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.
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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))
}),
)
}

Expand Down Expand Up @@ -253,18 +248,18 @@ 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.
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
})
}

Expand All @@ -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.
Expand All @@ -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) -> {
Expand All @@ -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()
}
}
}
Expand All @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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 })
Expand Down
2 changes: 1 addition & 1 deletion src/barnacle/dns.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
6 changes: 2 additions & 4 deletions src/barnacle/local_epmd.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -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, "@")
Expand All @@ -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 }))
}
Loading