1+ use std:: sync:: Arc ;
2+
13use tokio:: sync:: oneshot;
24
35use intersect_ingress_proxy_common:: configuration:: get_configuration;
4- use intersect_ingress_proxy_common:: protocols:: amqp:: subscribe:: broker_consumer_loop;
5- use intersect_ingress_proxy_common:: protocols:: amqp:: {
6- get_connection_pool, verify_connection_pool,
6+ use intersect_ingress_proxy_common:: protocols:: {
7+ amqp:: AmqpProtoHandler , mqtt:: MqttProtoHandler , ProtoHandler ,
78} ;
89use intersect_ingress_proxy_common:: telemetry:: {
910 get_json_subscriber, get_pretty_subscriber, init_subscriber,
1011} ;
1112
1213use proxy_http_server:: {
13- broadcaster:: Broadcaster , configuration:: Settings , webapp:: WebApplication ,
14+ broadcaster:: Broadcaster ,
15+ configuration:: Settings ,
16+ webapp_server:: { AmqpWebApplication , MqttWebApplication , WebApplication } ,
17+ APPLICATION_NAME ,
1418} ;
1519
16- const APPLICATION_NAME : & str = "proxy-http-server" ;
17-
1820// Muslc has a slow allocator, but we can only use jemalloc on 64-bit systems since jemalloc doesn't support i686.
1921#[ cfg( all( target_env = "musl" , target_pointer_width = "64" ) ) ]
2022#[ global_allocator]
2123static ALLOC : jemallocator:: Jemalloc = jemallocator:: Jemalloc ;
2224
25+ async fn begin_execution (
26+ configuration : Settings ,
27+ proto_handler : impl ProtoHandler ,
28+ application : impl WebApplication ,
29+ broadcaster : Arc < Broadcaster > ,
30+ ) -> anyhow:: Result < ( ) > {
31+ // How this works:
32+ // - Pass in the receiver to the broker consumer loop
33+ // - In the broker consumer loop, use tokio::select! to wait for rx.recv() at key points
34+ // - After the HTTP server has been shut down, drop the sender from memory, which will trigger an rx.recv() command
35+ // - This allows us to "finish up" publishing a message to our broker before killing the application.
36+ let ( tx, rx) = oneshot:: channel ( ) ;
37+
38+ let broker_join_handle =
39+ proto_handler. begin_subscribe_loop ( configuration. topic_prefix . clone ( ) , broadcaster, rx) ;
40+
41+ drop ( configuration) ;
42+
43+ application. run_until_stopped ( ) . await ?;
44+
45+ tracing:: info!( "Application shutting down, please wait for cleanups..." ) ;
46+ drop ( tx) ;
47+ broker_join_handle. await ?;
48+
49+ Ok ( ( ) )
50+ }
51+
2352#[ tokio:: main]
2453async fn main ( ) -> anyhow:: Result < ( ) > {
2554 let configuration = get_configuration :: < Settings > ( ) . expect ( "Failed to read configuration" ) ;
@@ -37,39 +66,39 @@ async fn main() -> anyhow::Result<()> {
3766 init_subscriber ( subscriber) ;
3867 }
3968
40- // set up broker connection pool
41- let pool = get_connection_pool ( & configuration. broker ) ;
42- if let Err ( msg) = verify_connection_pool ( & pool, APPLICATION_NAME ) . await {
43- tracing:: error!( msg) ;
44- std:: process:: exit ( 1 ) ;
45- }
46-
4769 let broadcaster = Broadcaster :: new ( ) ;
48- let application =
49- WebApplication :: build ( & configuration, broadcaster. clone ( ) , pool. clone ( ) ) . await ?;
50-
51- // How this works:
52- // - Pass in the receiver to the broker consumer loop
53- // - In the broker consumer loop, use tokio::select! to wait for rx.recv() at key points
54- // - After the HTTP server has been shut down, drop the sender from memory, which will trigger an rx.recv() command
55- // - This allows us to "finish up" publishing a message to our broker before killing the application.
56- let ( tx, rx) = oneshot:: channel ( ) ;
57-
58- let broker_join_handle = broker_consumer_loop (
59- pool,
60- configuration. topic_prefix . clone ( ) ,
61- APPLICATION_NAME . into ( ) ,
62- broadcaster,
63- rx,
64- ) ;
65-
66- drop ( configuration) ;
67-
68- application. run_until_stopped ( ) . await ?;
69-
70- tracing:: info!( "Application shutting down, please wait for cleanups..." ) ;
71- drop ( tx) ;
72- broker_join_handle. await ?;
73-
74- Ok ( ( ) )
70+ match configuration. broker . protocol {
71+ intersect_ingress_proxy_common:: configuration:: Protocol :: Amqp => {
72+ let proto_handler =
73+ AmqpProtoHandler :: new ( & configuration. broker , APPLICATION_NAME ) . await ;
74+ if proto_handler. is_err ( ) {
75+ tracing:: error!( "{}" , proto_handler. unwrap_err( ) ) ;
76+ std:: process:: exit ( 1 ) ;
77+ }
78+ let proto_handler = proto_handler. unwrap ( ) ;
79+ let web_server = AmqpWebApplication :: build (
80+ & configuration,
81+ broadcaster. clone ( ) ,
82+ proto_handler. clone ( ) ,
83+ )
84+ . await ?;
85+ begin_execution ( configuration, proto_handler, web_server, broadcaster) . await
86+ }
87+ intersect_ingress_proxy_common:: configuration:: Protocol :: Mqtt => {
88+ let proto_handler =
89+ MqttProtoHandler :: new ( & configuration. broker , APPLICATION_NAME ) . await ;
90+ if proto_handler. is_err ( ) {
91+ tracing:: error!( "{}" , proto_handler. unwrap_err( ) ) ;
92+ std:: process:: exit ( 1 ) ;
93+ }
94+ let proto_handler = proto_handler. unwrap ( ) ;
95+ let web_server = MqttWebApplication :: build (
96+ & configuration,
97+ broadcaster. clone ( ) ,
98+ proto_handler. clone ( ) ,
99+ )
100+ . await ?;
101+ begin_execution ( configuration, proto_handler, web_server, broadcaster) . await
102+ }
103+ }
75104}
0 commit comments