Skip to main content

nil_server/server/
remote.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use crate::app::App;
5use crate::error::Result;
6use crate::router;
7use crate::server::spawn_round_duration_task;
8use nil_core::world::World;
9use nil_server_database::Database;
10use nil_server_database::sql_types::game_id::GameId;
11use nil_server_types::round::RoundDuration;
12use std::net::SocketAddr;
13use std::sync::Weak;
14use tokio::sync::RwLock;
15use tokio::task::spawn;
16
17pub async fn start(database_url: String) -> Result<()> {
18  let app = App::new_remote(&database_url).await?;
19  let router = router::create()
20    .with_state(app)
21    .into_make_service_with_connect_info::<SocketAddr>();
22
23  let (listener, _) = super::bind(3000).await?;
24  axum::serve(listener, router).await?;
25
26  Ok(())
27}
28
29#[bon::builder]
30pub(crate) fn on_next_round(
31  database: Database,
32  weak_world: Weak<RwLock<World>>,
33  #[builder(into)] round_duration: Option<RoundDuration>,
34) -> Box<dyn Fn(&mut World) + Send + Sync> {
35  Box::new(move |world: &mut World| {
36    let id = world.id();
37    let database = database.clone();
38
39    world.save(move |bytes| {
40      let id = GameId::from(id);
41      if let Err(err) = database
42        .blocking()
43        .update_game_blob(id, &bytes)
44      {
45        tracing::error!(message = %err, error = ?err);
46      }
47    });
48
49    if let Some(duration) = round_duration {
50      let round = world.round().id();
51      let weak_world = Weak::clone(&weak_world);
52      spawn(spawn_round_duration_task(round, weak_world, duration));
53    }
54  })
55}