1- use crate :: commands:: command_executor_service:: CommandExecutorService ;
1+ use crate :: commands:: command_executor_service:: { ChatMessage , CommandExecutorService } ;
22use crate :: commands:: twitch_service:: TwitchService ;
33use crate :: db:: ProdDB ;
4- use service_oauth:: oauth_service:: OAuthService ;
54use crate :: session_service:: SessionService ;
6- use rand:: distr:: Alphanumeric ;
7- use rand:: Rng ;
85use serde:: { Deserialize , Serialize } ;
6+ use service_oauth:: oauth_service:: OAuthService ;
97use sqlx:: MySqlPool ;
108use std:: str:: FromStr ;
11- use std:: sync:: { Arc , RwLock } ;
9+ use std:: sync:: { Arc , OnceLock , RwLock } ;
1210use tokio:: runtime:: Handle ;
11+ use tokio:: sync:: broadcast:: error:: RecvError ;
1312use url:: Url ;
1413
1514mod webserver_authentication;
@@ -26,27 +25,71 @@ pub async fn start() {
2625 //check if all mandatory configuration values are set
2726 //start mini webserver
2827
28+ // L0, mini-webserver stage
2929 let db_connection = MySqlPool :: connect ( std:: env:: var ( "DATABASE_URL" ) . unwrap ( ) . as_str ( ) ) . await . unwrap ( ) ;
3030 let prod_db = ProdDB :: new ( db_connection) ;
3131 println ! ( "established db connection" ) ;
3232
33- let app_state = Arc :: new ( AppState {
34- session_service : SessionService :: default ( ) ,
35- oauth_service : OAuthService :: default ( ) ,
36- twitch_service : TwitchService :: new ( ) ,
37- prod_db,
33+ // 1st Stage
34+ let l1 = Arc :: new ( L1State {
3835 webserver_config : RwLock :: new ( WebserverConfig {
3936 panel_base_url : Url :: from_str ( "http://localhost:4771/panel" ) . unwrap ( ) ,
4037 server_base_url : Url :: from_str ( "http://localhost:4771" ) . unwrap ( ) ,
4138 panel_auth_twitch_client_id : "zmxjjn3xmncg8ewew6tjk08tub26bb" . to_string ( )
4239 } ) ,
43- command_executor_service : CommandExecutorService :: default ( ) ,
40+ oauth_service : Default :: default ( ) ,
41+ session_service : Default :: default ( ) ,
42+ prod_db,
4443 } ) ;
45- let a2 = app_state. clone ( ) ;
44+
45+ // Start Prod Webserver
46+ let webserver_state = Arc :: new ( WebserverState {
47+ l1 : l1. clone ( ) ,
48+ l2 : OnceLock :: new ( ) ,
49+ } ) ;
50+ let a2 = webserver_state. clone ( ) ;
4651 Handle :: current ( ) . spawn ( async { axum:: axum ( 4771 , a2) . await } ) ;
4752
48- let oauth = app_state. oauth_service . new_oauth_request ( "twitch" . to_string ( ) , "account" . to_string ( ) , "" . to_string ( ) , OAuthService :: random_state ( ) ) ;
53+ // 2nc Stage
54+ let service = TwitchService :: new ( l1. clone ( ) , ( ) ) . await . unwrap ( ) ;
55+ let l2 = Arc :: new ( L2State {
56+ twitch_service : service,
57+ command_executor_service : Default :: default ( ) ,
58+ } ) ;
59+
60+ // 3rd. (Full) Stage
61+ let _ = webserver_state. l2 . set ( l2. clone ( ) ) ;
62+ let full = Arc :: new ( FullState {
63+ l1,
64+ l2,
65+ } ) ;
66+
67+ let oauth = full. l1 . oauth_service . new_oauth_request ( "twitch" . to_string ( ) , "account" . to_string ( ) , "" . to_string ( ) , OAuthService :: random_state ( ) ) ;
4968 println ! ( "oauth: {:?}" , oauth) ;
69+
70+ let ( command_channel, _) = tokio:: sync:: broadcast:: channel :: < Box < ChatMessage > > ( 20 ) ;
71+ // fanout of messages
72+ let full2 = full. clone ( ) ;
73+ let sender2 = command_channel. clone ( ) ;
74+ Handle :: current ( ) . spawn ( async { TwitchService :: start_websocket ( full2, sender2) } ) ;
75+ let mut receiver = command_channel. subscribe ( ) ;
76+ let full2 = full. clone ( ) ;
77+ Handle :: current ( ) . spawn ( async {
78+ loop {
79+ let message = match receiver. recv ( ) . await {
80+ Ok ( m) => * m,
81+ Err ( RecvError :: Closed ) => return ,
82+ Err ( RecvError :: Lagged ( _s) ) => {
83+ // log skip
84+ continue ;
85+ }
86+ } ;
87+ let full = full2. clone ( ) ;
88+ Handle :: current ( ) . spawn ( async move {
89+ CommandExecutorService :: process_chat_message ( & full. l2 . command_executor_service , full, message) . await ;
90+ } ) ;
91+ }
92+ } ) ;
5093}
5194
5295#[ derive( Clone , Deserialize , Serialize ) ]
@@ -68,15 +111,28 @@ struct WebserverConfig {
68111 // maybe we need to add stuff like cors and disable auth here
69112}
70113
71- struct AppState {
114+ struct L1State {
72115 pub prod_db : ProdDB ,
73116 pub session_service : SessionService ,
74117 pub oauth_service : OAuthService ,
75118 pub webserver_config : RwLock < WebserverConfig > ,
119+ }
120+
121+ struct L2State {
76122 pub twitch_service : TwitchService ,
77123 pub command_executor_service : CommandExecutorService
78124}
79125
126+ struct WebserverState {
127+ pub l1 : Arc < L1State > ,
128+ pub l2 : OnceLock < Arc < L2State > > ,
129+ }
130+
131+ struct FullState {
132+ pub l1 : Arc < L1State > ,
133+ pub l2 : Arc < L2State > ,
134+ }
135+
80136#[ allow( dead_code) ]
81137mod _services {
82138 struct SetupWebserver ;
0 commit comments