server/services/queries/get_available_games.rs
1use chrono::{DateTime, Utc};
2
3use crate::{
4 convertors::available_game_row_to_available_game,
5 database::select_available_games,
6 domain::{AvailableGame, UserId},
7 error::{ServerError, bug},
8 server_state::ServerState,
9};
10
11/// Retrieves a list of available games that the specified user can play or join.
12///
13/// This function fetches games from the server that the specified user
14/// is eligible to join. Results can be filtered by a search string and
15/// paginated using the `last_created_at` parameter.
16///
17/// # Parameters
18///
19/// - `server_state`: The shared server state containing the games database.
20/// - `user_id`: The ID of the user requesting the available games.
21/// - `filter`: A string used to filter games by name or other criteria.
22/// - `last_created_at`: Optional timestamp for pagination; only games created
23/// after this timestamp are returned.
24///
25/// # Returns
26///
27/// Returns a tuple `(games, has_more, last_created_at)`:
28/// - `games`: A `Vec<AvailableGame>` containing the available games matching
29/// the filter and pagination criteria.
30/// - `has_more`: `true` if there are more games to fetch beyond this page.
31/// - `last_created_at`: The timestamp of the last game returned, to be used
32/// for the next paginated request.
33///
34/// Returns a `ServerError` if there is a problem accessing the database or
35/// processing the request.
36pub async fn get_available_games(
37 server_state: ServerState,
38 user_id: UserId,
39 filter: String,
40 last_created_at: Option<DateTime<Utc>>,
41) -> Result<(Vec<AvailableGame>, bool, Option<DateTime<Utc>>), ServerError> {
42 let pool = server_state.pool.clone();
43 const CHUNK_SIZE: u32 = 5;
44
45 let filter = (!filter.is_empty()).then_some(filter);
46
47 let chunk =
48 select_available_games(&*pool, CHUNK_SIZE, last_created_at, filter, user_id.value())
49 .await
50 .map_err(bug!())?;
51
52 let games = chunk
53 .games
54 .into_iter()
55 .map(|row| {
56 let game = available_game_row_to_available_game(row).map_err(bug!())?;
57 Ok::<_, ServerError>(game)
58 })
59 .collect::<Result<Vec<_>, _>>()?;
60
61 Ok((games, chunk.has_more, chunk.last_created_at))
62}