nil_server/server/
remote.rs1use 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}