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
710pub 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
1334pub 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
3166pub 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" )
85154fn 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+ }
0 commit comments