11pub mod models;
22
3- use anyhow:: { anyhow , Context , Result } ;
3+ use anyhow:: { Context , Result } ;
44use log:: info;
55use minio:: s3:: types:: S3Api ;
66use once_cell:: sync:: Lazy ;
7- use std:: {
8- sync:: { Arc , Mutex } ,
9- time:: Duration ,
10- } ;
7+ use std:: { sync:: Arc , time:: Duration } ;
118
129use sea_orm:: { ConnectOptions , Database , DatabaseConnection } ;
1310
14- pub static PG_CONN : Lazy < Arc < Mutex < Option < DatabaseConnection > > > > =
15- Lazy :: new ( || Arc :: new ( Mutex :: new ( None ) ) ) ;
16- pub static REDIS_CONN : Lazy < Arc < Mutex < Option < redis :: Client > > > > =
17- Lazy :: new ( || Arc :: new ( Mutex :: new ( None ) ) ) ;
18- pub static MINIO_CONN : Lazy < Arc < Mutex < Option < minio:: s3:: Client > > > > =
19- Lazy :: new ( || Arc :: new ( Mutex :: new ( None ) ) ) ;
11+ # [ derive ( Debug , Clone ) ]
12+ pub struct DatabaseConnectionMap {
13+ pub pg_conn : DatabaseConnection ,
14+ pub redis_conn : redis :: Client ,
15+ pub minio_conn : minio:: s3:: Client ,
16+ }
2017
21- pub async fn init ( ) -> Result < ( ) > {
22- PG_CONN
23- . lock ( )
24- . map_err ( |err| anyhow ! ( format!( "Failed to lock PG_CONN: {}" , err) ) ) ?
25- . replace (
26- Database :: connect ( {
27- let mut opt = ConnectOptions :: new ( format ! (
28- "postgres://{}:{}@{}:{}/{}" ,
29- std:: env:: var( "DB_USERNAME" ) . unwrap_or( "genshin_map" . into( ) ) ,
30- std:: env:: var( "DB_PASSWORD" ) . unwrap_or( "" . into( ) ) ,
31- std:: env:: var( "DB_HOST" ) . unwrap_or( "localhost" . into( ) ) ,
32- std:: env:: var( "DB_PORT" )
33- . map( |str | str . parse:: <u16 >( ) . unwrap( ) )
34- . unwrap_or( 5432 ) ,
35- std:: env:: var( "DB_DATABASE" ) . unwrap_or( "genshin_map" . into( ) ) ,
36- ) ) ;
37- opt. max_connections ( 100 )
38- . min_connections ( 5 )
39- . connect_timeout ( Duration :: from_secs ( 8 ) )
40- . acquire_timeout ( Duration :: from_secs ( 8 ) )
41- . idle_timeout ( Duration :: from_secs ( 8 ) )
42- . max_lifetime ( Duration :: from_secs ( 8 ) )
43- . sqlx_logging ( true )
44- . sqlx_logging_level ( log:: LevelFilter :: Trace ) ;
45- opt
46- } )
47- . await ?,
48- ) ;
49- info ! ( "Postgres is ready" ) ;
18+ pub static DB_CONN : Lazy < Arc < DatabaseConnectionMap > > = Lazy :: new ( || {
19+ Arc :: new ( {
20+ tokio:: runtime:: Builder :: new_current_thread ( )
21+ . enable_all ( )
22+ . build ( )
23+ . expect ( "Failed to create Tokio runtime" )
24+ . block_on ( init ( ) )
25+ . expect ( "Failed to initialize database connections" )
26+ } )
27+ } ) ;
5028
51- REDIS_CONN
52- . lock ( )
53- . map_err ( |err| anyhow ! ( format!( "Failed to lock REDIS_CONN: {}" , err) ) ) ?
54- . replace ( redis:: Client :: open ( format ! (
55- "redis://{}{}@{}:{}/{}" ,
56- std:: env:: var( "REDIS_USERNAME" ) . unwrap_or( "" . into( ) ) ,
57- std:: env:: var( "REDIS_PASSWORD" )
58- . map( |p| format!( ":{}" , p) )
59- . unwrap_or_default( ) ,
60- std:: env:: var( "REDIS_HOST" ) . unwrap_or( "localhost" . into( ) ) ,
61- std:: env:: var( "REDIS_PORT" )
29+ pub async fn init ( ) -> Result < DatabaseConnectionMap > {
30+ // Postgres
31+ let pg_conn = {
32+ let mut opt = ConnectOptions :: new ( format ! (
33+ "postgres://{}:{}@{}:{}/{}" ,
34+ std:: env:: var( "DB_USERNAME" ) . unwrap_or( "genshin_map" . into( ) ) ,
35+ std:: env:: var( "DB_PASSWORD" ) . unwrap_or( "" . into( ) ) ,
36+ std:: env:: var( "DB_HOST" ) . unwrap_or( "localhost" . into( ) ) ,
37+ std:: env:: var( "DB_PORT" )
6238 . map( |str | str . parse:: <u16 >( ) . unwrap( ) )
63- . unwrap_or( 6379 ) ,
64- 1 ,
65- ) ) ?) ;
39+ . unwrap_or( 5432 ) ,
40+ std:: env:: var( "DB_DATABASE" ) . unwrap_or( "genshin_map" . into( ) ) ,
41+ ) ) ;
42+ opt. max_connections ( 100 )
43+ . min_connections ( 5 )
44+ . connect_timeout ( Duration :: from_secs ( 8 ) )
45+ . acquire_timeout ( Duration :: from_secs ( 8 ) )
46+ . idle_timeout ( Duration :: from_secs ( 8 ) )
47+ . max_lifetime ( Duration :: from_secs ( 8 ) )
48+ . sqlx_logging ( true )
49+ . sqlx_logging_level ( log:: LevelFilter :: Trace ) ;
50+ Database :: connect ( opt) . await ?
51+ } ;
52+ info ! ( "Postgres is ready" ) ;
53+
54+ // Redis
55+ let redis_conn = redis:: Client :: open ( format ! (
56+ "redis://{}{}@{}:{}/{}" ,
57+ std:: env:: var( "REDIS_USERNAME" ) . unwrap_or( "" . into( ) ) ,
58+ std:: env:: var( "REDIS_PASSWORD" )
59+ . map( |p| format!( ":{}" , p) )
60+ . unwrap_or_default( ) ,
61+ std:: env:: var( "REDIS_HOST" ) . unwrap_or( "localhost" . into( ) ) ,
62+ std:: env:: var( "REDIS_PORT" )
63+ . map( |str | str . parse:: <u16 >( ) . unwrap( ) )
64+ . unwrap_or( 6379 ) ,
65+ 1 ,
66+ ) ) ?;
6667 info ! ( "Redis is ready" ) ;
6768
68- MINIO_CONN
69- . lock ( )
70- . map_err ( |err| anyhow ! ( format!( "Failed to lock MINIO_CONN: {}" , err) ) ) ?
71- . replace ( minio:: s3:: Client :: new (
69+ // MinIO
70+ let minio_conn = {
71+ let client = minio:: s3:: Client :: new (
7272 std:: env:: var ( "MINIO_BASE_URL" )
7373 . unwrap_or ( "http://localhost:9000" . into ( ) )
7474 . parse ( ) ?,
@@ -79,57 +79,40 @@ pub async fn init() -> Result<()> {
7979 ) ) ) ,
8080 None ,
8181 None ,
82- ) ?) ;
83- if let Some ( conn) = MINIO_CONN
84- . lock ( )
85- . map_err ( |err| anyhow ! ( format!( "Failed to lock MINIO_CONN: {}" , err) ) ) ?
86- . as_mut ( )
87- {
88- if !conn. bucket_exists ( "images" ) . send ( ) . await ?. exists {
89- conn. create_bucket ( "images" ) . send ( ) . await ?;
90- let config = serde_json:: json!( {
91- "Version" : "2012-10-17" ,
92- "Statement" : [
93- {
94- "Effect" : "Allow" ,
95- "Principal" : "*" ,
96- "Action" : [
97- "s3:GetObject"
98- ] ,
99- "Resource" : "arn:aws:s3:::images/*"
100- }
101- ]
102- } )
103- . to_string ( ) ;
104- conn. put_bucket_policy ( "images" )
105- . config ( config)
106- . send ( )
107- . await ?;
108- }
82+ ) ?;
10983
110- if !conn. bucket_exists ( "bz2doc" ) . send ( ) . await ?. exists {
111- conn. create_bucket ( "bz2doc" ) . send ( ) . await ?;
112- let config = serde_json:: json!( {
113- "Version" : "2012-10-17" ,
114- "Statement" : [
115- {
116- "Effect" : "Allow" ,
117- "Principal" : "*" ,
118- "Action" : [
119- "s3:GetObject"
120- ] ,
121- "Resource" : "arn:aws:s3:::bz2doc/*"
122- }
123- ]
124- } )
125- . to_string ( ) ;
126- conn. put_bucket_policy ( "bz2doc" )
127- . config ( config)
128- . send ( )
129- . await ?;
84+ // Ensure buckets exist and set policy
85+ for bucket in [ "images" , "bz2doc" ] {
86+ if !client. bucket_exists ( bucket) . send ( ) . await ?. exists {
87+ client. create_bucket ( bucket) . send ( ) . await ?;
88+ let config = serde_json:: json!( {
89+ "Version" : "2012-10-17" ,
90+ "Statement" : [
91+ {
92+ "Effect" : "Allow" ,
93+ "Principal" : "*" ,
94+ "Action" : [
95+ "s3:GetObject"
96+ ] ,
97+ "Resource" : format!( "arn:aws:s3:::{}/*" , bucket)
98+ }
99+ ]
100+ } )
101+ . to_string ( ) ;
102+ client
103+ . put_bucket_policy ( bucket)
104+ . config ( config)
105+ . send ( )
106+ . await ?;
107+ }
130108 }
131- }
109+ client
110+ } ;
132111 info ! ( "MinIO is ready" ) ;
133112
134- Ok ( ( ) )
113+ Ok ( DatabaseConnectionMap {
114+ pg_conn,
115+ redis_conn,
116+ minio_conn,
117+ } )
135118}
0 commit comments