2020-04-08 20:13:45 +08:00
use std ::{ env , thread } ;
2019-11-22 02:15:33 +08:00
2020-04-11 01:40:43 +08:00
use actix_cors ::Cors ;
2020-04-15 16:51:15 +08:00
use actix_web ::{ middleware , HttpServer } ;
2019-10-31 22:09:23 +08:00
use main_error ::MainError ;
2020-05-19 18:22:51 +08:00
use meilisearch_http ::helpers ::NormalizePath ;
2020-06-30 20:42:16 +08:00
use meilisearch_http ::{ create_app , index_update_callback , Data , Opt } ;
2020-04-11 01:05:05 +08:00
use structopt ::StructOpt ;
2020-07-02 22:20:45 +08:00
use meilisearch_http ::snapshot ;
2019-10-31 22:09:23 +08:00
2019-11-22 02:15:33 +08:00
mod analytics ;
2019-11-25 21:51:47 +08:00
#[ cfg(target_os = " linux " ) ]
2019-10-31 22:09:23 +08:00
#[ global_allocator ]
static ALLOC : jemallocator ::Jemalloc = jemallocator ::Jemalloc ;
2020-04-25 00:18:40 +08:00
#[ actix_rt::main ]
2020-04-07 23:47:35 +08:00
async fn main ( ) -> Result < ( ) , MainError > {
2019-11-20 00:09:06 +08:00
let opt = Opt ::from_args ( ) ;
2019-11-16 00:33:06 +08:00
2020-05-14 16:42:01 +08:00
#[ cfg(all(not(debug_assertions), feature = " sentry " )) ]
2020-05-07 22:34:20 +08:00
let _sentry = sentry ::init ( (
2020-06-30 20:42:16 +08:00
if ! opt . no_sentry {
Some ( opt . sentry_dsn . clone ( ) )
} else {
None
} ,
2020-05-10 16:52:44 +08:00
sentry ::ClientOptions {
release : sentry ::release_name! ( ) ,
.. Default ::default ( )
} ,
2020-05-07 22:34:20 +08:00
) ) ;
2020-02-06 22:42:35 +08:00
match opt . env . as_ref ( ) {
" production " = > {
if opt . master_key . is_none ( ) {
2020-02-27 01:49:17 +08:00
return Err (
" In production mode, the environment variable MEILI_MASTER_KEY is mandatory "
. into ( ) ,
) ;
2020-02-06 22:42:35 +08:00
}
2020-05-07 22:58:48 +08:00
2020-05-14 16:42:01 +08:00
#[ cfg(all(not(debug_assertions), feature = " sentry " )) ]
2020-06-30 20:42:16 +08:00
if ! opt . no_sentry & & _sentry . is_enabled ( ) {
sentry ::integrations ::panic ::register_panic_handler ( ) ; // TODO: This shouldn't be needed when upgrading to sentry 0.19.0. These integrations are turned on by default when using `sentry::init`.
2020-05-07 22:34:20 +08:00
sentry ::integrations ::env_logger ::init ( None , Default ::default ( ) ) ;
}
2020-04-11 01:05:05 +08:00
}
2020-02-06 22:42:35 +08:00
" development " = > {
env_logger ::from_env ( env_logger ::Env ::default ( ) . default_filter_or ( " info " ) ) . init ( ) ;
2020-02-27 01:49:17 +08:00
}
2020-02-06 22:42:35 +08:00
_ = > unreachable! ( ) ,
}
2020-07-02 22:20:45 +08:00
if let Some ( path ) = & opt . load_from_snapshot {
snapshot ::load_snapshot ( & opt . db_path , path , opt . ignore_snapshot_if_db_exists , opt . ignore_missing_snapshot ) ? ;
}
2020-06-24 22:06:04 +08:00
let data = Data ::new ( opt . clone ( ) ) ? ;
2020-05-27 01:03:13 +08:00
2020-02-06 22:42:35 +08:00
if ! opt . no_analytics {
2020-05-27 01:03:13 +08:00
let analytics_data = data . clone ( ) ;
let analytics_opt = opt . clone ( ) ;
2020-06-30 20:42:16 +08:00
thread ::spawn ( move | | analytics ::analytics_sender ( analytics_data , analytics_opt ) ) ;
2019-11-22 02:15:33 +08:00
}
2019-11-16 00:33:06 +08:00
let data_cloned = data . clone ( ) ;
data . db . set_update_callback ( Box ::new ( move | name , status | {
2020-04-08 20:13:45 +08:00
index_update_callback ( name , & data_cloned , status ) ;
2019-11-16 00:33:06 +08:00
} ) ) ;
2020-07-02 22:20:45 +08:00
if let Some ( path ) = & opt . snapshot_path {
snapshot ::schedule_snapshot ( data . clone ( ) , & path , opt . snapshot_interval_sec ) ? ;
}
2020-02-06 22:42:35 +08:00
print_launch_resume ( & opt , & data ) ;
2020-05-10 16:52:44 +08:00
let http_server = HttpServer ::new ( move | | {
2020-04-15 16:51:15 +08:00
create_app ( & data )
2020-04-11 01:40:43 +08:00
. wrap (
Cors ::new ( )
2020-04-15 00:00:35 +08:00
. send_wildcard ( )
2020-06-30 20:42:16 +08:00
. allowed_headers ( vec! [ " content-type " , " x-meili-api-key " ] )
2020-05-30 04:16:42 +08:00
. max_age ( 86_400 ) // 24h
2020-04-15 00:00:35 +08:00
. finish ( ) ,
2020-04-11 01:40:43 +08:00
)
. wrap ( middleware ::Logger ::default ( ) )
. wrap ( middleware ::Compress ::default ( ) )
2020-05-19 18:22:51 +08:00
. wrap ( NormalizePath )
2020-05-10 16:52:44 +08:00
} ) ;
if let Some ( config ) = opt . get_ssl_config ( ) ? {
http_server
. bind_rustls ( opt . http_addr , config ) ?
. run ( )
. await ? ;
} else {
http_server . bind ( opt . http_addr ) ? . run ( ) . await ? ;
}
2019-10-31 22:09:23 +08:00
Ok ( ( ) )
2019-10-31 22:00:36 +08:00
}
2020-02-06 22:42:35 +08:00
pub fn print_launch_resume ( opt : & Opt , data : & Data ) {
let ascii_name = r #"
888 b d888 d8b 888 d8b . d8888b . 888
8888 b d8888 Y8P 888 Y8P d88P Y88b 888
88888 b . d88888 888 Y88b . 888
888 Y88888P888 . d88b . 888 888 888 " Y888b. .d88b. 8888b. 888d888 .d8888b 88888b.
888 Y888P 888 d8P Y8b 888 888 888 " Y88b. d8P Y8b " 88 b 888 P " d88P " 888 " 88b
888 Y8P 888 88888888 888 888 888 " 888 88888888 .d888888 888 888 888 888
888 " 888 Y8b. 888 888 888 Y88b d88P Y8b. 888 888 888 Y88b. 888 888
888 888 " Y8888 888 888 888 " Y8888P " " Y8888 " Y888888 888 " Y8888P 888 888
" #;
2020-05-14 16:04:18 +08:00
eprintln! ( " {} " , ascii_name ) ;
2020-02-06 22:42:35 +08:00
2020-05-14 16:04:18 +08:00
eprintln! ( " Database path: \t \t {:?} " , opt . db_path ) ;
eprintln! ( " Server listening on: \t {:?} " , opt . http_addr ) ;
eprintln! ( " Environment: \t \t {:?} " , opt . env ) ;
eprintln! ( " Commit SHA: \t \t {:?} " , env! ( " VERGEN_SHA " ) . to_string ( ) ) ;
eprintln! (
" Build date: \t \t {:?} " ,
2020-02-27 01:49:17 +08:00
env! ( " VERGEN_BUILD_TIMESTAMP " ) . to_string ( )
) ;
2020-05-14 16:04:18 +08:00
eprintln! (
" Package version: \t {:?} " ,
2020-02-27 01:49:17 +08:00
env! ( " CARGO_PKG_VERSION " ) . to_string ( )
) ;
2020-02-06 22:42:35 +08:00
2020-06-30 20:42:16 +08:00
#[ cfg(all(not(debug_assertions), feature = " sentry " )) ]
eprintln! (
" Sentry DSN: \t \t {:?} " ,
if ! opt . no_sentry {
& opt . sentry_dsn
} else {
" Disabled "
}
) ;
2020-07-01 23:54:48 +08:00
eprintln! (
" Amplitude Analytics: \t {:?} " ,
if ! opt . no_analytics {
" Enabled "
} else {
" Disabled "
}
) ;
2020-05-14 16:04:18 +08:00
eprintln! ( ) ;
2020-05-19 16:24:03 +08:00
if data . api_keys . master . is_some ( ) {
eprintln! ( " A Master Key has been set. Requests to MeiliSearch won't be authorized unless you provide an authentication key. " ) ;
2020-02-06 22:42:35 +08:00
} else {
2020-05-14 16:04:18 +08:00
eprintln! ( " No master key found; The server will accept unidentified requests. \
If you need some protection in development mode , please export a key : export MEILI_MASTER_KEY = xxx " );
2020-02-06 22:42:35 +08:00
}
2020-05-14 16:04:18 +08:00
eprintln! ( ) ;
2020-05-29 21:46:00 +08:00
eprintln! ( " Documentation: \t \t https://docs.meilisearch.com " ) ;
eprintln! ( " Source code: \t \t https://github.com/meilisearch/meilisearch " ) ;
2020-05-14 16:04:18 +08:00
eprintln! ( " Contact: \t \t https://docs.meilisearch.com/resources/contact.html or bonjour@meilisearch.com " ) ;
eprintln! ( ) ;
2020-02-06 22:42:35 +08:00
}