1
0
Files
AstralRinth/src/scheduler.rs
Geometrically f0b73fd696 Change index interval, add slug to search documents (#110)
* Change index interval, add slug to search documents

* Allow the removal of '@' for slug get

* Fix

* Remove name and rename side type

* Run prepare
2020-12-13 18:10:58 -07:00

167 lines
4.8 KiB
Rust

use actix_rt::time;
use actix_rt::Arbiter;
use futures::StreamExt;
pub struct Scheduler {
arbiter: Arbiter,
}
impl Scheduler {
pub fn new() -> Self {
Scheduler {
arbiter: Arbiter::new(),
}
}
pub fn run<F, R>(&mut self, interval: std::time::Duration, mut task: F)
where
F: FnMut() -> R + Send + 'static,
R: std::future::Future<Output = ()> + Send + 'static,
{
let future = time::interval(interval).for_each_concurrent(2, move |_| task());
self.arbiter.send(future);
}
}
impl Drop for Scheduler {
fn drop(&mut self) {
self.arbiter.stop();
}
}
use log::{info, warn};
pub fn schedule_versions(
scheduler: &mut Scheduler,
pool: sqlx::Pool<sqlx::Postgres>,
skip_initial: bool,
) {
let version_index_interval = std::time::Duration::from_secs(
dotenv::var("VERSION_INDEX_INTERVAL")
.ok()
.map(|i| i.parse().unwrap())
.unwrap_or(1800),
);
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>,
#[serde(rename = "releaseTime")]
release_time: chrono::DateTime<chrono::Utc>,
}
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;
// A list of version names that contains spaces.
// Generated using the command
// ```sh
// curl https://launchermeta.mojang.com/mc/game/version_manifest.json \
// | jq '[.versions[].id | select(contains(" "))]'
// ```
const HALL_OF_SHAME: [(&str, &str); 12] = [
("1.14.2 Pre-Release 4", "1.14.2-pre4"),
("1.14.2 Pre-Release 3", "1.14.2-pre3"),
("1.14.2 Pre-Release 2", "1.14.2-pre2"),
("1.14.2 Pre-Release 1", "1.14.2-pre1"),
("1.14.1 Pre-Release 2", "1.14.1-pre2"),
("1.14.1 Pre-Release 1", "1.14.1-pre1"),
("1.14 Pre-Release 5", "1.14-pre5"),
("1.14 Pre-Release 4", "1.14-pre4"),
("1.14 Pre-Release 3", "1.14-pre3"),
("1.14 Pre-Release 2", "1.14-pre2"),
("1.14 Pre-Release 1", "1.14-pre1"),
("3D Shareware v1.34", "3D-Shareware-v1.34"),
];
for version in input.versions.into_iter() {
let mut name = version.id;
if !name
.chars()
.all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c))
{
if let Some((_, alternate)) = HALL_OF_SHAME.iter().find(|(version, _)| name == *version)
{
name = String::from(*alternate);
} else {
// 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_)?
.created(&version.release_time)
.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(())
}