mirror of
https://codeberg.org/spire/depot-prefetch.git
synced 2026-06-03 10:04:09 +02:00
add watch command
This commit is contained in:
parent
182b067fad
commit
c89efc87e7
3 changed files with 164 additions and 18 deletions
90
Cargo.lock
generated
90
Cargo.lock
generated
|
|
@ -513,6 +513,8 @@ dependencies = [
|
||||||
"steam-vent",
|
"steam-vent",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
"vdf-reader",
|
"vdf-reader",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1245,6 +1247,16 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||||
|
dependencies = [
|
||||||
|
"overload",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num"
|
name = "num"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
|
@ -1396,6 +1408,12 @@ version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "overload"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot_core"
|
name = "parking_lot_core"
|
||||||
version = "0.9.11"
|
version = "0.9.11"
|
||||||
|
|
@ -1977,6 +1995,15 @@ dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
|
@ -2255,6 +2282,15 @@ dependencies = [
|
||||||
"syn 2.0.103",
|
"syn 2.0.103",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
|
|
@ -2449,6 +2485,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||||
|
dependencies = [
|
||||||
|
"nu-ansi-term",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2530,6 +2592,12 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vdf-reader"
|
name = "vdf-reader"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
|
@ -2694,6 +2762,28 @@ dependencies = [
|
||||||
"rustix",
|
"rustix",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
|
|
|
||||||
|
|
@ -14,3 +14,5 @@ tokio = { version = "1.45.1", features = ["macros", "rt-multi-thread"] }
|
||||||
main_error = "0.1.2"
|
main_error = "0.1.2"
|
||||||
clap = { version = "4.5.40", features = ["derive"] }
|
clap = { version = "4.5.40", features = ["derive"] }
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
|
tracing = "0.1.41"
|
||||||
|
tracing-subscriber = "0.3.19"
|
||||||
86
src/main.rs
86
src/main.rs
|
|
@ -1,8 +1,12 @@
|
||||||
use crate::prefetch::prefetch;
|
use std::process::Command;
|
||||||
|
use std::time::Duration;
|
||||||
|
use crate::prefetch::{prefetch, PrefetchError};
|
||||||
use crate::product_info::{ProductInfoError, ProductInfoFetcher};
|
use crate::product_info::{ProductInfoError, ProductInfoFetcher};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use main_error::MainResult;
|
use main_error::MainResult;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod prefetch;
|
mod prefetch;
|
||||||
|
|
@ -11,15 +15,17 @@ mod product_info;
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
struct Args {
|
struct Args {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: Command,
|
command: ArgsCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
enum Command {
|
enum ArgsCommand {
|
||||||
/// Get the latest manifest and pre-fetch it
|
/// Get the latest manifest and pre-fetch it
|
||||||
Fetch(ProductArgs),
|
Fetch(ProductArgs),
|
||||||
/// Get the latest manifest without fetching
|
/// Get the latest manifest without fetching
|
||||||
Manifest(ProductArgs),
|
Manifest(ProductArgs),
|
||||||
|
/// Watch for manifest changes and pre-fetch any updates
|
||||||
|
Watch(WatchArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
|
|
@ -34,32 +40,68 @@ struct ProductArgs {
|
||||||
depot: Vec<u32>,
|
depot: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
struct WatchArgs {
|
||||||
|
#[clap(flatten)]
|
||||||
|
product_args: ProductArgs,
|
||||||
|
/// How often to check for updates
|
||||||
|
#[clap(long, default_value_t = 300)]
|
||||||
|
interval: u64,
|
||||||
|
/// Command to run when updates are detected, the manifest data will be passed as the first argument as json.
|
||||||
|
#[clap(long)]
|
||||||
|
run: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> MainResult {
|
async fn main() -> MainResult {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
let info_fetcher = ProductInfoFetcher::new().await?;
|
let info_fetcher = ProductInfoFetcher::new().await?;
|
||||||
|
|
||||||
match args.command {
|
match args.command {
|
||||||
Command::Fetch(args) => {
|
ArgsCommand::Fetch(args) => {
|
||||||
let inputs = get_manifests(&info_fetcher, &args).await?;
|
let inputs = get_manifests(&info_fetcher, &args).await?;
|
||||||
let outputs = inputs.into_iter()
|
let outputs = fetch_inputs(inputs)?;
|
||||||
.map(|input| {
|
|
||||||
prefetch(&input).map(|hash| ManifestOutput {
|
|
||||||
app_id: input.app_id,
|
|
||||||
depot_id: input.depot_id,
|
|
||||||
manifest: input.manifest,
|
|
||||||
hash,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
|
|
||||||
serde_json::to_writer_pretty(std::io::stdout(), &outputs)?;
|
serde_json::to_writer_pretty(std::io::stdout(), &outputs)?;
|
||||||
}
|
}
|
||||||
Command::Manifest(args) => {
|
ArgsCommand::Manifest(args) => {
|
||||||
let inputs = get_manifests(&info_fetcher, &args).await?;
|
let inputs = get_manifests(&info_fetcher, &args).await?;
|
||||||
serde_json::to_writer_pretty(std::io::stdout(), &inputs)?;
|
serde_json::to_writer_pretty(std::io::stdout(), &inputs)?;
|
||||||
}
|
}
|
||||||
|
ArgsCommand::Watch(args) => {
|
||||||
|
let mut last_inputs = get_manifests(&info_fetcher, &args.product_args).await?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
sleep(Duration::from_secs(args.interval)).await;
|
||||||
|
let new_inputs = get_manifests(&info_fetcher, &args.product_args).await?;
|
||||||
|
if new_inputs != last_inputs {
|
||||||
|
last_inputs = new_inputs.clone();
|
||||||
|
let inputs_json = serde_json::to_string(&new_inputs)?;
|
||||||
|
debug!(inputs = inputs_json, "updated detected");
|
||||||
|
|
||||||
|
let outputs = fetch_inputs(new_inputs)?;
|
||||||
|
let output_json = serde_json::to_string(&outputs)?;
|
||||||
|
info!(outputs = ?output_json, "prefetch complete");
|
||||||
|
|
||||||
|
if let Some(run) = args.run.as_deref() {
|
||||||
|
match Command::new(run)
|
||||||
|
.arg(output_json)
|
||||||
|
.status() {
|
||||||
|
Ok(status) => {
|
||||||
|
info!(%status, "Command existed");
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
error!(%error, "Failed to run command");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -91,7 +133,19 @@ async fn get_manifests(
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
fn fetch_inputs(inputs: impl IntoIterator<Item = ManifestInput>) -> Result<Vec<ManifestOutput>, PrefetchError> {
|
||||||
|
inputs.into_iter()
|
||||||
|
.map(|input| {
|
||||||
|
prefetch(&input).map(|hash| ManifestOutput {
|
||||||
|
app_id: input.app_id,
|
||||||
|
depot_id: input.depot_id,
|
||||||
|
manifest: input.manifest,
|
||||||
|
hash,
|
||||||
|
})
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Eq, PartialEq, Copy, Clone)]
|
||||||
struct ManifestInput {
|
struct ManifestInput {
|
||||||
app_id: u32,
|
app_id: u32,
|
||||||
depot_id: u32,
|
depot_id: u32,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue