Skip to content

Commit

Permalink
refactor(native-app): change the way the logging, sdk and server is i…
Browse files Browse the repository at this point in the history
…nstantiated
  • Loading branch information
meskill committed Sep 3, 2022
1 parent e4f522f commit 7a8e980
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 85 deletions.
1 change: 1 addition & 0 deletions native-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "mystic_light_browser_cinema"
version = "0.1.0"
edition = "2021"
default-run = "app"

[dependencies]
async-graphql = { version="4.0.1", features=["tracing"] }
Expand Down
16 changes: 4 additions & 12 deletions native-app/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use async_graphql_axum::{GraphQLBatchRequest, GraphQLResponse};
use axum::{extract::Extension, routing::get, routing::post, Router};
use mystic_light_sdk::{CommonError, MysticLightSDK};
use mystic_light_sdk::MysticLightSDK;
use tower_http::{
cors::{Any, CorsLayer},
trace::TraceLayer,
Expand All @@ -19,18 +19,10 @@ async fn healthz() -> &'static str {
"Ok"
}

const LIB_PATH: &str = if cfg!(target_arch = "x86_64") {
"./sdk/MysticLight_SDK_x64.dll"
} else {
"./sdk/MysticLight_SDK.dll"
};

pub fn create_app() -> Result<Router, CommonError> {
let sdk = MysticLightSDK::new(LIB_PATH)?;

pub fn create_app(sdk: MysticLightSDK) -> Router {
let schema = create_qraphql_schema(sdk);

Ok(Router::new()
Router::new()
.route("/mystic_light", post(graphql))
.route("/healthz", get(healthz))
.layer(TraceLayer::new_for_http())
Expand All @@ -40,5 +32,5 @@ pub fn create_app() -> Result<Router, CommonError> {
.allow_methods(Any)
.allow_origin(Any)
.allow_headers(Any),
))
)
}
55 changes: 6 additions & 49 deletions native-app/src/bin/app.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,11 @@
use mystic_light_browser_cinema::start_server;
use tracing_subscriber::filter::EnvFilter;
use tracing_subscriber::fmt::format::FmtSpan;
use mystic_light_browser_cinema::{log::start_logging, AppBuilder};

const LOG_DEFAULT_DIRECTIVES: &str = "mystic_light_sdk=debug,mystic_light_browser_cinema=debug";
fn main() -> Result<(), Box<dyn std::error::Error>> {
start_logging();

fn main() {
let env_filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new(LOG_DEFAULT_DIRECTIVES));
let app = AppBuilder::new().with_random_port(false).build()?;

#[cfg(debug_assertions)]
tracing_subscriber::fmt()
.pretty()
.with_env_filter(env_filter)
.with_span_events(FmtSpan::FULL)
.init();
app.listen()?;

#[cfg(not(debug_assertions))]
{
const LOG_FILES_LIMIT: usize = 5;
const LOG_FILE_BYTES_LIMIT: usize = 20 * 1024 * 1024;
const LOG_DIR_NAME: &str = "logs";
const LOG_FILE_NAME: &str = "log.txt";

use file_rotate::{
compression::Compression, suffix::AppendCount, ContentLimit, FileRotate,
};
use std::env;
use std::sync::Mutex;

let mut log_dir = env::current_exe().unwrap();

log_dir.pop();
log_dir.push(LOG_DIR_NAME);
log_dir.push(LOG_FILE_NAME);

let log_rotation = FileRotate::new(
log_dir,
AppendCount::new(LOG_FILES_LIMIT),
ContentLimit::Bytes(LOG_FILE_BYTES_LIMIT),
Compression::OnRotate(0),
);

tracing_subscriber::fmt()
.pretty()
.with_env_filter(env_filter)
.with_ansi(false)
.with_span_events(FmtSpan::FULL)
.with_writer(Mutex::new(log_rotation))
.init();
}

start_server();
Ok(())
}
146 changes: 122 additions & 24 deletions native-app/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,145 @@
mod app;
mod graphql;
pub mod log;
mod props;
mod sdk;

use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use axum::Router;
use mystic_light_sdk::{CommonError, MysticLightSDK};
use tokio::sync::mpsc;

use app::create_app;
use props::Props;
use sdk::create_sdk;

const STATIC_PORT: u16 = 5000;
const MAX_ATTEMPTS_SDK_INIT: u8 = 1;

fn resolve_random_port() -> Option<u16> {
portpicker::pick_unused_port()
}

#[cfg(debug_assertions)]
fn resolve_port() -> u16 {
5000
pub struct AppBuilder {
random_port: bool,
shutdown_rx: Option<mpsc::Receiver<()>>,
max_attempts_sdk_init: u8,
}

#[cfg(not(debug_assertions))]
fn resolve_port() -> u16 {
portpicker::pick_unused_port().expect("Cannot resolve free port")
impl Default for AppBuilder {
fn default() -> Self {
Self {
random_port: false,
shutdown_rx: None,
max_attempts_sdk_init: MAX_ATTEMPTS_SDK_INIT,
}
}
}

pub fn start_server() {
let port = resolve_port();
impl AppBuilder {
pub fn new() -> Self {
AppBuilder::default()
}

pub fn with_random_port(&mut self, random_port: bool) -> &mut Self {
self.random_port = random_port;

self
}

pub fn with_channel_rx(&mut self, shutdown_rx: mpsc::Receiver<()>) -> &mut Self {
self.shutdown_rx = Some(shutdown_rx);

self
}

pub fn with_max_attempts_sdk_init(&mut self, max_attempts: u8) -> &mut Self {
assert!(max_attempts > 0, "max_attempts should be more than 0");

self.max_attempts_sdk_init = max_attempts;

self
}

pub fn build(&mut self) -> Result<App, CommonError> {
let port = if self.random_port {
resolve_random_port().expect("Cannot resolve port")
} else {
STATIC_PORT
};

let mut attempts = 0u8;

let sdk = loop {
attempts += 1;

tracing::info!("trying to resolve sdk for {attempts} attempt");

let sdk = create_sdk();

if sdk.is_ok() || attempts == self.max_attempts_sdk_init {
break sdk;
}
}?;

App::new(sdk, port, self.shutdown_rx.take())
}
}

pub struct App {
port: u16,
router: Router,
shutdown_rx: Option<mpsc::Receiver<()>>,
}

impl App {
fn new(
sdk: MysticLightSDK,
port: u16,
shutdown_rx: Option<mpsc::Receiver<()>>,
) -> Result<Self, CommonError> {
let router = create_app(sdk);

Ok(Self {
router,
port,
shutdown_rx,
})
}

pub fn listen(self) -> Result<(), Box<dyn std::error::Error>> {
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), self.port);

let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.max_blocking_threads(1)
.build()?;

let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port);
runtime.block_on(async {
let server = axum::Server::bind(&addr).serve(self.router.into_make_service());

let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.max_blocking_threads(1)
.build()
.unwrap();
let local_address = server.local_addr();

runtime.block_on(async {
let app = create_app();
tracing::info!("Server started at {}", local_address);

let server = axum::Server::bind(&addr)
.serve(app.expect("Cannot initialize sdk").into_make_service());
let props = Props::new(local_address);

let local_address = server.local_addr();
props.save()?;

tracing::info!("Server started at {}", local_address);
if let Some(mut shutdown_rx) = self.shutdown_rx {
let graceful = server.with_graceful_shutdown(async {
shutdown_rx.recv().await;

let props = Props::new(local_address);
tracing::info!("Shutting down the server");
});

props.save().unwrap();
graceful.await?;
} else {
server.await?;
}

server.await.unwrap();
})
Ok(())
})
}
}
61 changes: 61 additions & 0 deletions native-app/src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::panic;

use tracing_subscriber::filter::EnvFilter;
use tracing_subscriber::fmt::format::FmtSpan;

const LOG_DEFAULT_DIRECTIVES: &str =
"mystic_light_sdk=debug,mystic_light_browser_cinema=debug,install=debug,uninstall=debug,service=debug";

pub fn start_logging() {
let env_filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new(LOG_DEFAULT_DIRECTIVES));

#[cfg(debug_assertions)]
tracing_subscriber::fmt()
.pretty()
.with_env_filter(env_filter)
.with_span_events(FmtSpan::FULL)
.init();

#[cfg(not(debug_assertions))]
{
const LOG_FILES_LIMIT: usize = 5;
const LOG_FILE_BYTES_LIMIT: usize = 20 * 1024 * 1024;
const LOG_DIR_NAME: &str = "logs";
const LOG_FILE_NAME: &str = "log.txt";

use file_rotate::{
compression::Compression, suffix::AppendCount, ContentLimit, FileRotate,
};
use std::env;
use std::sync::Mutex;

let mut log_dir = env::current_exe().unwrap();

log_dir.pop();
log_dir.push(LOG_DIR_NAME);
log_dir.push(LOG_FILE_NAME);

let log_rotation = FileRotate::new(
log_dir,
AppendCount::new(LOG_FILES_LIMIT),
ContentLimit::Bytes(LOG_FILE_BYTES_LIMIT),
Compression::OnRotate(0),
);

tracing_subscriber::fmt()
.pretty()
.with_env_filter(env_filter)
.with_ansi(false)
.with_span_events(FmtSpan::FULL)
.with_writer(Mutex::new(log_rotation))
.init();
}

panic::set_hook(Box::new(|panic_info| {
let payload = panic_info.payload().downcast_ref::<&str>();
let location = panic_info.location();

tracing::error!("Panic at {location:?} with\n{payload:?}");
}))
}
11 changes: 11 additions & 0 deletions native-app/src/sdk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use mystic_light_sdk::{CommonError, MysticLightSDK};

const LIB_PATH: &str = if cfg!(target_arch = "x86_64") {
"./sdk/MysticLight_SDK_x64.dll"
} else {
"./sdk/MysticLight_SDK.dll"
};

pub fn create_sdk() -> Result<MysticLightSDK, CommonError> {
MysticLightSDK::new(LIB_PATH)
}

0 comments on commit 7a8e980

Please sign in to comment.