Skip to content

Commit 09ca835

Browse files
committed
fix: only return active maps
1 parent 6a5cd82 commit 09ca835

File tree

5 files changed

+68
-22
lines changed

5 files changed

+68
-22
lines changed

src/database/mod.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use anyhow::anyhow;
55
use futures::stream::FuturesUnordered;
66
use futures::StreamExt;
77
use mars_api_rs_macro::IdentifiableDocument;
8+
use mongodb::bson::Document;
89
use mongodb::{bson::{doc, oid::ObjectId}, Client, Collection, Cursor, options::{ClientOptions, FindOneOptions, UpdateOptions}, results::DeleteResult};
910
use mongodb::options::FindOptions;
1011
use rand::Rng;
@@ -14,7 +15,7 @@ use serde::Serialize;
1415

1516
use models::tag::Tag;
1617

17-
use crate::{database::models::player::Player, util::r#macro::unwrap_helper};
18+
use crate::database::models::player::Player;
1819
use crate::database::models::ip_identity::IpIdentity;
1920
use crate::database::models::player::SimplePlayer;
2021
use crate::util::validation::verbose_result_ok;
@@ -106,6 +107,19 @@ impl Database {
106107
}
107108
}
108109

110+
pub async fn get_all_active_maps(&self, time: u64) -> Vec<Level> {
111+
let cursor =
112+
match Level::get_collection(&self)
113+
.find(doc! { "updatedAt": { "$gte": time as i64 } }, None).await {
114+
Ok(cursor) => cursor,
115+
Err(e) => {
116+
warn!("Error retrieving latest maps: {}", e);
117+
return Vec::new();
118+
}
119+
};
120+
Self::consume_cursor_into_owning_vec_option(Some(cursor)).await
121+
}
122+
109123
pub async fn ensure_player_name_uniqueness(&self, name: &String, keep_id: &String) {
110124
let num: u16;
111125
{
@@ -206,6 +220,15 @@ impl Database {
206220
R::get_collection(&self).find_one(doc! { "nameLower": name.to_lowercase() }, None).await.unwrap_or(None)
207221
}
208222

223+
pub async fn find_by_fields<R>(&self, value: &str, field_names: Vec<String>) -> Option<R>
224+
where R: CollectionOwner<R> + Serialize + IdentifiableDocument + DeserializeOwned + Unpin + Send + Sync {
225+
let conditions: Vec<Document> = field_names
226+
.iter()
227+
.map(|name| doc! { name: value })
228+
.collect();
229+
R::get_collection(&self).find_one(doc! { "$or": conditions }, None).await.unwrap_or(None)
230+
}
231+
209232
pub async fn get_recent_matches(&self, limit: i64) -> Vec<Match> {
210233
let opts = FindOptions::builder().sort(doc! { "loadedAt": -1 }).limit(limit).build();
211234
let cursor = self.matches.find(doc! {}, Some(opts)).await.ok();

src/database/models/level.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ pub struct Level {
1515
pub loaded_at: u64,
1616
pub name: String,
1717
pub name_lower: String,
18+
#[serde(default)]
19+
pub slug: Option<String>,
1820
pub version: String,
1921
pub gamemodes: Vec<LevelGamemode>,
2022
pub updated_at: u64,

src/http/map/mod.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use std::path::{Path, PathBuf};
1+
use std::{path::Path, sync::Arc};
22

3-
use futures::{StreamExt, future::join_all};
3+
use futures::{FutureExt, StreamExt, future::join_all};
44
use image::{create_image_decoder, parse_image_data};
55
use mongodb::bson::doc;
66
use rocket::{Build, Data, Rocket, State, data::ToByteUnit, fs::FileServer, serde::json::Json};
7+
use tokio::sync::RwLock;
78
use tokio_util::codec::FramedRead;
89

910
use crate::{MarsAPIState, database::{Database, models::level::{Level, LevelRecords}}, http::map::payload::MapLoadOneRequest, util::{auth::AuthorizationToken, error::ApiErrorResponder, r#macro::unwrap_helper, stream::LengthPrefixedDataDecoder, time::get_u64_time_millis}};
@@ -17,14 +18,16 @@ async fn add_maps(
1718
maps: Json<Vec<MapLoadOneRequest>>,
1819
_auth_guard: AuthorizationToken
1920
) -> Json<Vec<Level>> {
20-
let mut map_list = maps.0;
21-
debug!("maps incoming are {:?}", &map_list);
21+
let map_list = maps.0;
2222
let map_list_length = map_list.len();
2323
let time_millis = get_u64_time_millis();
2424
let mut maps_to_save : Vec<Level> = Vec::new();
2525

2626
let query_tasks : Vec<_> = map_list.iter().map(|map| {
27-
state.database.find_by_name::<Level>(&map.name)
27+
state.database.find_by_fields::<Level>(
28+
map.slug.as_ref().unwrap_or(&map.name),
29+
vec![String::from("slug"), String::from("nameLower")]
30+
)
2831
}).collect();
2932
let level_docs = join_all(query_tasks).await;
3033
for (map, level_opt) in map_list.into_iter().zip(level_docs) {
@@ -44,6 +47,7 @@ async fn add_maps(
4447
id: map.id,
4548
name: map.name,
4649
name_lower: lowercase_map_name,
50+
slug: map.slug,
4751
version: map.version,
4852
gamemodes: map.gamemodes,
4953
loaded_at: time_millis,
@@ -57,8 +61,23 @@ async fn add_maps(
5761
});
5862
}
5963

60-
let save_tasks : Vec<_> = maps_to_save.iter().map(|map| { state.database.save(map) }).collect();
61-
join_all(save_tasks).await;
64+
65+
let tasks = {
66+
let mut all_tasks = Vec::new();
67+
let save_tasks : Vec<_> =
68+
maps_to_save.iter().map(|map| { state.database.save(map).boxed() }).collect();
69+
let update_map_state = {
70+
let rwlock = state.map_state.last_update.clone();
71+
async move {
72+
let mut timestamp = rwlock.write().await;
73+
*timestamp = time_millis;
74+
}.boxed()
75+
};
76+
all_tasks.extend(save_tasks);
77+
all_tasks.push(update_map_state);
78+
all_tasks
79+
};
80+
join_all(tasks).await;
6281

6382
info!("Received {} maps. Updating {} maps.", map_list_length, maps_to_save.len());
6483
Json(state.database.get_all_documents().await)
@@ -97,7 +116,7 @@ async fn add_map_images(
97116

98117
#[get("/")]
99118
async fn get_all_maps(state: &State<MarsAPIState>) -> Json<Vec<Level>> {
100-
Json(state.database.get_all_documents::<Level>().await)
119+
Json(state.database.get_all_active_maps(*state.map_state.last_update.read().await).await)
101120
}
102121

103122
#[get("/<map_id>")]
@@ -106,15 +125,9 @@ async fn get_map_by_id(state: &State<MarsAPIState>, map_id: &str) -> Result<Json
106125
Ok(Json(map))
107126
}
108127

109-
fn get_map_images_directory(state: &State<MarsAPIState>) -> Option<PathBuf> {
110-
match state.config.options.images_path.as_ref() {
111-
Some(path) => {
112-
let mut p = PathBuf::new();
113-
p.push(path);
114-
Some(p)
115-
},
116-
None => None
117-
}
128+
#[derive(Clone)]
129+
pub struct MapState {
130+
pub last_update: Arc<RwLock<u64>>
118131
}
119132

120133
pub fn mount(build: Rocket<Build>, state: &MarsAPIState) -> Rocket<Build> {

src/http/map/payload.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ pub struct MapLoadOneRequest {
77
#[serde(rename = "_id")]
88
pub id: String,
99
pub name: String,
10+
#[serde(default)]
11+
pub slug: Option<String>,
1012
pub version: String,
1113
pub gamemodes: Vec<LevelGamemode>,
1214
pub authors: Vec<LevelContributor>,

src/main.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use std::{env, marker::PhantomData, net::{IpAddr, Ipv4Addr}, path::PathBuf, sync
55
use anyhow::anyhow;
66
use config::{deserialize_mars_config, MarsConfig};
77
use database::{Database, cache::{Cache, get_redis_pool, RedisAdapter}, models::{player::Player, r#match::Match}};
8-
use http::map::image::{ImageState, image_queue_processor};
8+
use http::map::{MapState, image::{ImageState, image_queue_processor}};
99
use rocket::{figment::Figment, http::Method, Build, Config, Rocket, Shutdown};
1010
use rocket_cors::{AllowedOrigins, CorsOptions};
1111
use socket::leaderboard::MarsLeaderboards;
12-
use tokio::sync::Semaphore;
12+
use tokio::sync::{RwLock, Semaphore};
1313
use crate::database::migrations::MigrationExecutor;
1414

1515
use crate::socket::socket_handler::{SocketState, setup_socket};
@@ -48,7 +48,8 @@ pub struct MarsAPIState {
4848
pub player_cache: Arc<Cache<Player>>,
4949
pub match_cache: Arc<Cache<Match>>,
5050
pub leaderboards: Arc<MarsLeaderboards>,
51-
pub image_state: Arc<Option<ImageState>>
51+
pub image_state: Arc<Option<ImageState>>,
52+
pub map_state: Arc<MapState>
5253
}
5354

5455
fn rocket(state: MarsAPIState) -> Rocket<Build> {
@@ -205,7 +206,12 @@ async fn main() -> Result<(), String> {
205206
player_cache,
206207
match_cache,
207208
leaderboards,
208-
image_state
209+
image_state,
210+
map_state: Arc::new(MapState {
211+
last_update: Arc::new(
212+
RwLock::new(0)
213+
)
214+
})
209215
};
210216

211217

0 commit comments

Comments
 (0)