Support forking into background
This makes the JS action simpler.
This commit is contained in:
parent
ecced7bc94
commit
0e0bef15fb
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -251,6 +251,15 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "daemonize"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab8bfdaacb3c887a54d41bdf48d3af8873b3f5566469f8ba21b92057509f116e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derivative"
|
name = "derivative"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
@ -713,6 +722,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"clap",
|
"clap",
|
||||||
|
"daemonize",
|
||||||
"gha-cache",
|
"gha-cache",
|
||||||
"rand",
|
"rand",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -18,6 +18,7 @@ thiserror = "1.0.40"
|
||||||
tokio-stream = "0.1.14"
|
tokio-stream = "0.1.14"
|
||||||
tokio-util = { version = "0.7.8", features = ["io"] }
|
tokio-util = { version = "0.7.8", features = ["io"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
daemonize = "0.5.0"
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1.28.0"
|
version = "1.28.0"
|
||||||
|
|
|
@ -16,13 +16,16 @@
|
||||||
mod api;
|
mod api;
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
|
use std::fs::{self, File};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::os::fd::OwnedFd;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{extract::Extension, routing::get, Router};
|
use axum::{extract::Extension, routing::get, Router};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use tokio::fs;
|
use daemonize::Daemonize;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
use gha_cache::{Api, Credentials};
|
use gha_cache::{Api, Credentials};
|
||||||
|
@ -58,6 +61,12 @@ struct Args {
|
||||||
/// instead.
|
/// instead.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
upstream: Option<String>,
|
upstream: Option<String>,
|
||||||
|
|
||||||
|
/// Daemonize the server.
|
||||||
|
///
|
||||||
|
/// This is for use in the GitHub Action only.
|
||||||
|
#[arg(long, hide = true)]
|
||||||
|
daemon_dir: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The global server state.
|
/// The global server state.
|
||||||
|
@ -67,17 +76,14 @@ struct StateInner {
|
||||||
upstream: Option<String>,
|
upstream: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
fn main() {
|
||||||
async fn main() {
|
|
||||||
let args = Args::parse();
|
|
||||||
|
|
||||||
init_logging();
|
init_logging();
|
||||||
|
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
let credentials = if let Some(credentials_file) = &args.credentials_file {
|
let credentials = if let Some(credentials_file) = &args.credentials_file {
|
||||||
tracing::info!("Loading credentials from {:?}", credentials_file);
|
tracing::info!("Loading credentials from {:?}", credentials_file);
|
||||||
let bytes = fs::read(credentials_file)
|
let bytes = fs::read(credentials_file).expect("Failed to read credentials file");
|
||||||
.await
|
|
||||||
.expect("Failed to read credentials file");
|
|
||||||
|
|
||||||
serde_json::from_slice(&bytes).expect("Failed to deserialize credentials file")
|
serde_json::from_slice(&bytes).expect("Failed to deserialize credentials file")
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,13 +94,13 @@ async fn main() {
|
||||||
|
|
||||||
let mut api = Api::new(credentials).expect("Failed to initialize GitHub Actions Cache API");
|
let mut api = Api::new(credentials).expect("Failed to initialize GitHub Actions Cache API");
|
||||||
|
|
||||||
if let Some(cache_version) = args.cache_version {
|
if let Some(cache_version) = &args.cache_version {
|
||||||
api.mutate_version(cache_version.as_bytes());
|
api.mutate_version(cache_version.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = Arc::new(StateInner {
|
let state = Arc::new(StateInner {
|
||||||
api,
|
api,
|
||||||
upstream: args.upstream,
|
upstream: args.upstream.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let app = Router::new().route("/", get(root)).merge(api::get_router());
|
let app = Router::new().route("/", get(root)).merge(api::get_router());
|
||||||
|
@ -106,11 +112,28 @@ async fn main() {
|
||||||
|
|
||||||
let app = app.layer(Extension(state));
|
let app = app.layer(Extension(state));
|
||||||
|
|
||||||
tracing::info!("listening on {}", args.listen);
|
if args.daemon_dir.is_some() {
|
||||||
axum::Server::bind(&args.listen)
|
let dir = args.daemon_dir.as_ref().unwrap();
|
||||||
.serve(app.into_make_service())
|
let logfile: OwnedFd = File::create(dir.join("daemon.log")).unwrap().into();
|
||||||
.await
|
let daemon = Daemonize::new()
|
||||||
.unwrap();
|
.pid_file(dir.join("daemon.pid"))
|
||||||
|
.stdout(File::from(logfile.try_clone().unwrap()))
|
||||||
|
.stderr(File::from(logfile));
|
||||||
|
|
||||||
|
daemon.start().expect("Failed to fork into the background");
|
||||||
|
}
|
||||||
|
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
rt.block_on(async move {
|
||||||
|
tracing::info!("listening on {}", args.listen);
|
||||||
|
axum::Server::bind(&args.listen)
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.with_graceful_shutdown(async move {
|
||||||
|
shutdown_receiver.await.ok();
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_logging() {
|
fn init_logging() {
|
||||||
|
|
Loading…
Reference in a new issue