diff --git a/planetwars-server/src/db/matches.rs b/planetwars-server/src/db/matches.rs index b806dd3..22cb564 100644 --- a/planetwars-server/src/db/matches.rs +++ b/planetwars-server/src/db/matches.rs @@ -130,13 +130,34 @@ pub fn list_matches(amount: i64, conn: &PgConnection) -> QueryResult QueryResult> { +pub fn list_public_matches( + amount: i64, + before: Option, + after: Option, + conn: &PgConnection, +) -> QueryResult> { conn.transaction(|| { - let matches = matches::table + // TODO: how can this common logic be abstracted? + // TODO: this is not nice. Replace this with proper cursor logic. + let mut query = matches::table .filter(matches::is_public.eq(true)) - .order_by(matches::created_at.desc()) - .limit(amount) - .get_results::(conn)?; + .into_boxed(); + + query = match (before, after) { + (None, None) => query.order_by(matches::created_at.desc()), + (Some(before), None) => query + .filter(matches::created_at.lt(before)) + .order_by(matches::created_at.desc()), + (None, Some(after)) => query + .filter(matches::created_at.gt(after)) + .order_by(matches::created_at.asc()), + (Some(before), Some(after)) => query + .filter(matches::created_at.lt(before)) + .filter(matches::created_at.gt(after)) + .order_by(matches::created_at.desc()), + }; + + let matches = query.limit(amount).get_results::(conn)?; fetch_full_match_data(matches, conn) }) @@ -145,11 +166,15 @@ pub fn list_public_matches(amount: i64, conn: &PgConnection) -> QueryResult, + after: Option, conn: &PgConnection, ) -> QueryResult> { conn.transaction(|| { let matches = matches::table .filter(matches::is_public.eq(true)) + .filter(matches::created_at.nullable().lt(before)) + .filter(matches::created_at.nullable().gt(after)) .order_by(matches::created_at.desc()) .inner_join(match_players::table) .inner_join( diff --git a/planetwars-server/src/routes/matches.rs b/planetwars-server/src/routes/matches.rs index c1957d4..1b7581c 100644 --- a/planetwars-server/src/routes/matches.rs +++ b/planetwars-server/src/routes/matches.rs @@ -35,7 +35,6 @@ pub struct ApiMatchPlayer { pub struct ListRecentMatchesParams { count: Option, // TODO: should timezone be specified here? - // TODO: implement these before: Option, after: Option, @@ -58,9 +57,9 @@ pub async fn list_recent_matches( Some(bot_name) => { let bot = db::bots::find_bot_by_name(&bot_name, &conn) .map_err(|_| StatusCode::BAD_REQUEST)?; - matches::list_bot_matches(bot.id, count, &conn) + matches::list_bot_matches(bot.id, count, params.before, params.after, &conn) } - None => matches::list_public_matches(count, &conn), + None => matches::list_public_matches(count, params.before, params.after, &conn), }; matches