Skip to content

Commit ec8859d

Browse files
authored
Merge pull request #6 from renatillas/supervised
Supervised added + more error types!
2 parents e035fc5 + 6bd39aa commit ec8859d

File tree

8 files changed

+910
-241
lines changed

8 files changed

+910
-241
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
*.ez
33
/build
44
erl_crash.dump
5+
.claude

gleam.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ repository = { type = "github", user = "renatillas", repo = "carotte" }
1616
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
1717
amqp_client = ">= 4.0.3 and < 5.0.0"
1818
gleam_erlang = ">= 1.0.0 and < 2.0.0"
19+
gleam_otp = ">= 1.1.0 and < 2.0.0"
1920

2021
[dev-dependencies]
2122
gleeunit = ">= 1.0.0 and < 2.0.0"

manifest.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ packages = [
99
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
1010
{ name = "glance", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "FAA3DAC74AF71D47C67D88EB32CE629075169F878D148BB1FF225439BE30070A" },
1111
{ name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
12+
{ name = "gleam_otp", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "7987CBEBC8060B88F14575DEF546253F3116EBE2A5DA6FD82F38243FCE97C54B" },
1213
{ name = "gleam_stdlib", version = "0.62.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "0080706D3A5A9A36C40C68481D1D231D243AF602E6D2A2BE67BA8F8F4DFF45EC" },
1314
{ name = "gleeunit", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "FDC68A8C492B1E9B429249062CD9BAC9B5538C6FBF584817205D0998C42E1DAC" },
1415
{ name = "glexer", version = "2.2.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glexer", source = "hex", outer_checksum = "5C235CBDF4DA5203AD5EAB1D6D8B456ED8162C5424FE2309CFFB7EF438B7C269" },
@@ -23,5 +24,6 @@ packages = [
2324
amqp_client = { version = ">= 4.0.3 and < 5.0.0" }
2425
asset = { version = ">= 1.2.0 and < 2.0.0" }
2526
gleam_erlang = { version = ">= 1.0.0 and < 2.0.0" }
27+
gleam_otp = { version = ">= 1.1.0 and < 2.0.0" }
2628
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
2729
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }

src/carotte.gleam

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,39 @@
1-
import gleam/erlang/process.{type Pid}
1+
import gleam/erlang/process
2+
import gleam/otp/actor
3+
import gleam/otp/supervision
4+
import gleam/result
25

3-
pub type CarotteClient {
4-
CarotteClient(pid: Pid)
6+
pub opaque type Client {
7+
Client(name: process.Name(Message))
58
}
69

710
pub type CarotteError {
811
Blocked
912
Closed
1013
AuthFailure(String)
14+
ProcessNotFound
15+
AlreadyRegistered(String)
16+
NotFound(String)
17+
AccessRefused(String)
18+
PreconditionFailed(String)
19+
ResourceLocked(String)
20+
ChannelClosed(String)
21+
ConnectionRefused(String)
22+
ConnectionTimeout(String)
23+
FrameError(String)
24+
InternalError(String)
25+
InvalidPath(String)
26+
NoRoute(String)
27+
NotAllowed(String)
28+
NotImplemented(String)
29+
UnexpectedFrame(String)
30+
CommandInvalid(String)
31+
UnknownError(String)
1132
}
1233

1334
pub opaque type Builder {
1435
Builder(
36+
name: process.Name(Message),
1537
username: String,
1638
password: String,
1739
virtual_host: String,
@@ -24,8 +46,21 @@ pub opaque type Builder {
2446
)
2547
}
2648

27-
pub fn default_client() -> Builder {
28-
Builder("guest", "guest", "/", "localhost", 5672, 2074, 0, 10, 60_000)
49+
pub type Message
50+
51+
pub fn default_client(name name: process.Name(Message)) -> Builder {
52+
Builder(
53+
name: name,
54+
username: "guest",
55+
password: "guest",
56+
virtual_host: "/",
57+
host: "localhost",
58+
port: 5672,
59+
channel_max: 2074,
60+
frame_max: 0,
61+
heartbeat: 10,
62+
connection_timeout: 60_000,
63+
)
2964
}
3065

3166
pub fn with_username(builder: Builder, username: String) -> Builder {
@@ -67,22 +102,57 @@ pub fn with_connection_timeout(
67102
Builder(..builder, connection_timeout:)
68103
}
69104

70-
pub fn start(builder: Builder) -> Result(CarotteClient, CarotteError) {
71-
do_start(
72-
builder.username,
73-
builder.password,
74-
builder.virtual_host,
75-
builder.host,
76-
builder.port,
77-
builder.channel_max,
78-
builder.frame_max,
79-
builder.heartbeat,
80-
builder.connection_timeout,
105+
pub fn start(builder: Builder) -> actor.StartResult(Client) {
106+
use pid <- result.try(
107+
do_start(
108+
builder.name,
109+
builder.username,
110+
builder.password,
111+
builder.virtual_host,
112+
builder.host,
113+
builder.port,
114+
builder.channel_max,
115+
builder.frame_max,
116+
builder.heartbeat,
117+
builder.connection_timeout,
118+
)
119+
|> result.map_error(with: fn(carotte_error) {
120+
case carotte_error {
121+
Blocked -> actor.InitFailed("Blocked connection")
122+
Closed -> actor.InitFailed("Closed connection")
123+
AuthFailure(reason) -> actor.InitFailed("AuthFailure: " <> reason)
124+
ProcessNotFound -> actor.InitFailed("Process not found")
125+
AlreadyRegistered(reason) ->
126+
actor.InitFailed("AlreadyRegistered: " <> reason)
127+
NotFound(reason) -> actor.InitFailed("NotFound: " <> reason)
128+
AccessRefused(reason) -> actor.InitFailed("AccessRefused: " <> reason)
129+
PreconditionFailed(reason) ->
130+
actor.InitFailed("PreconditionFailed: " <> reason)
131+
ResourceLocked(reason) -> actor.InitFailed("ResourceLocked: " <> reason)
132+
ChannelClosed(reason) -> actor.InitFailed("ChannelClosed: " <> reason)
133+
ConnectionRefused(reason) ->
134+
actor.InitFailed("ConnectionRefused: " <> reason)
135+
ConnectionTimeout(reason) ->
136+
actor.InitFailed("ConnectionTimeout: " <> reason)
137+
FrameError(reason) -> actor.InitFailed("FrameError: " <> reason)
138+
InternalError(reason) -> actor.InitFailed("InternalError: " <> reason)
139+
InvalidPath(reason) -> actor.InitFailed("InvalidPath: " <> reason)
140+
NoRoute(reason) -> actor.InitFailed("NoRoute: " <> reason)
141+
NotAllowed(reason) -> actor.InitFailed("NotAllowed: " <> reason)
142+
NotImplemented(reason) -> actor.InitFailed("NotImplemented: " <> reason)
143+
UnexpectedFrame(reason) ->
144+
actor.InitFailed("UnexpectedFrame: " <> reason)
145+
CommandInvalid(reason) -> actor.InitFailed("CommandInvalid: " <> reason)
146+
UnknownError(reason) -> actor.InitFailed("UnknownError: " <> reason)
147+
}
148+
}),
81149
)
150+
Ok(actor.Started(pid, named_client(builder.name)))
82151
}
83152

84153
@external(erlang, "carotte_ffi", "start")
85154
fn do_start(
155+
name: process.Name(Message),
86156
username: String,
87157
password: String,
88158
virtual_host: String,
@@ -92,11 +162,19 @@ fn do_start(
92162
frame_max: Int,
93163
heartbeat: Int,
94164
connection_timeout: Int,
95-
) -> Result(CarotteClient, CarotteError)
165+
) -> Result(process.Pid, CarotteError)
96166

97-
pub fn close(client: CarotteClient) -> Result(Nil, CarotteError) {
167+
pub fn close(client: Client) -> Result(Nil, CarotteError) {
98168
do_close(client)
99169
}
100170

101171
@external(erlang, "carotte_ffi", "close")
102-
fn do_close(client: CarotteClient) -> Result(Nil, CarotteError)
172+
fn do_close(client: Client) -> Result(Nil, CarotteError)
173+
174+
pub fn supervised(builder: Builder) -> supervision.ChildSpecification(Client) {
175+
supervision.worker(fn() { start(builder) })
176+
}
177+
178+
pub fn named_client(name: process.Name(Message)) -> Client {
179+
Client(name)
180+
}

src/carotte/channel.gleam

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ pub type Channel {
66
}
77

88
/// Open a channel to a RabbitMQ server
9-
pub fn open_channel(carotte_client: carotte.CarotteClient) {
10-
do_open_channel(carotte_client)
9+
pub fn open_channel(client: carotte.Client) {
10+
do_open_channel(client)
1111
}
1212

1313
@external(erlang, "carotte_ffi", "open_channel")
1414
fn do_open_channel(
15-
carotte_client: carotte.CarotteClient,
15+
carotte_client: carotte.Client,
1616
) -> Result(Channel, carotte.CarotteError)

0 commit comments

Comments
 (0)