You've already forked AstralRinth
forked from didirus/AstralRinth
Game Version types, indexing, and bugfixes (#91)
* Add types to game_versions, allow filtering by version type - Fixes an issue with version numbers in the initial mod indexing queue - Modifies the /api/v1/categories/game_versions route to take an optional query parameter `type` to filter the listed game versions - Creating tags is now idempotent - Creating game_versions now requires a JSON body that specifies the version type * Implement automatic indexing of new Minecraft versions It's currently set to run every 6 hours and isn't configurable; we could add config for it, but it doesn't seem likely to be rate limited or have issues with frequency.
This commit is contained in:
103
src/scheduler.rs
103
src/scheduler.rs
@@ -28,3 +28,106 @@ impl Drop for Scheduler {
|
||||
self.arbiter.stop();
|
||||
}
|
||||
}
|
||||
|
||||
use log::{info, warn};
|
||||
|
||||
pub fn schedule_versions(
|
||||
scheduler: &mut Scheduler,
|
||||
pool: sqlx::Pool<sqlx::Postgres>,
|
||||
skip_initial: bool,
|
||||
) {
|
||||
// Check mojang's versions every 6 hours
|
||||
let version_index_interval = std::time::Duration::from_secs(60 * 60 * 6);
|
||||
|
||||
let mut skip = skip_initial;
|
||||
scheduler.run(version_index_interval, move || {
|
||||
let pool_ref = pool.clone();
|
||||
let local_skip = skip;
|
||||
if skip {
|
||||
skip = false;
|
||||
}
|
||||
async move {
|
||||
if local_skip {
|
||||
return;
|
||||
}
|
||||
info!("Indexing game versions list from Mojang");
|
||||
let result = update_versions(&pool_ref).await;
|
||||
if let Err(e) = result {
|
||||
warn!("Version update failed: {}", e);
|
||||
}
|
||||
info!("Done indexing game versions");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum VersionIndexingError {
|
||||
#[error("Network error while updating game versions list: {0}")]
|
||||
NetworkError(#[from] reqwest::Error),
|
||||
#[error("Database error while updating game versions list: {0}")]
|
||||
DatabaseError(#[from] crate::database::models::DatabaseError),
|
||||
}
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct InputFormat<'a> {
|
||||
// latest: LatestFormat,
|
||||
versions: Vec<VersionFormat<'a>>,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct VersionFormat<'a> {
|
||||
id: String,
|
||||
#[serde(rename = "type")]
|
||||
type_: std::borrow::Cow<'a, str>,
|
||||
}
|
||||
|
||||
async fn update_versions(pool: &sqlx::Pool<sqlx::Postgres>) -> Result<(), VersionIndexingError> {
|
||||
let input = reqwest::get("https://launchermeta.mojang.com/mc/game/version_manifest.json")
|
||||
.await?
|
||||
.json::<InputFormat>()
|
||||
.await?;
|
||||
|
||||
let mut skipped_versions_count = 0u32;
|
||||
|
||||
for version in input.versions.into_iter() {
|
||||
let name = version.id;
|
||||
if !name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c))
|
||||
{
|
||||
// We'll deal with these manually
|
||||
skipped_versions_count += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let type_ = match &*version.type_ {
|
||||
"release" => "release",
|
||||
"snapshot" => "snapshot",
|
||||
"old_alpha" => "alpha",
|
||||
"old_beta" => "beta",
|
||||
_ => "other",
|
||||
};
|
||||
|
||||
crate::database::models::categories::GameVersion::builder()
|
||||
.version(&name)?
|
||||
.version_type(type_)?
|
||||
.insert(pool)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if skipped_versions_count > 0 {
|
||||
// This will currently always trigger due to 1.14 pre releases
|
||||
// and the shareware april fools update. We could set a threshold
|
||||
// that accounts for those versions and update it whenever we
|
||||
// manually fix another version.
|
||||
warn!(
|
||||
"Skipped {} game versions; check for new versions and add them manually",
|
||||
skipped_versions_count
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user