diff options
Diffstat (limited to 'src/routes/instances.rs')
| -rw-r--r-- | src/routes/instances.rs | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/src/routes/instances.rs b/src/routes/instances.rs index e4f62f0..8dd6a62 100644 --- a/src/routes/instances.rs +++ b/src/routes/instances.rs | |||
| @@ -19,7 +19,6 @@ struct InstanceListTemplate { | |||
| 19 | is_superuser: bool, | 19 | is_superuser: bool, |
| 20 | password_change_required: bool, | 20 | password_change_required: bool, |
| 21 | instances: Vec<InstanceInfo>, | 21 | instances: Vec<InstanceInfo>, |
| 22 | has_active: bool, | ||
| 23 | } | 22 | } |
| 24 | 23 | ||
| 25 | #[derive(Template)] | 24 | #[derive(Template)] |
| @@ -42,7 +41,6 @@ struct EditInstanceTemplate { | |||
| 42 | instance: Instance, | 41 | instance: Instance, |
| 43 | current_seed: Option<String>, | 42 | current_seed: Option<String>, |
| 44 | max_memory_mb: u32, | 43 | max_memory_mb: u32, |
| 45 | error: Option<String>, | ||
| 46 | } | 44 | } |
| 47 | 45 | ||
| 48 | struct InstanceInfo { | 46 | struct InstanceInfo { |
| @@ -119,7 +117,6 @@ async fn list_instances( | |||
| 119 | .filter_map(|r| r.ok()) | 117 | .filter_map(|r| r.ok()) |
| 120 | .collect(); | 118 | .collect(); |
| 121 | 119 | ||
| 122 | let has_active = instances.iter().any(|i| i.is_active); | ||
| 123 | drop(stmt); | 120 | drop(stmt); |
| 124 | drop(conn); | 121 | drop(conn); |
| 125 | 122 | ||
| @@ -128,7 +125,6 @@ async fn list_instances( | |||
| 128 | is_superuser: account.is_superuser, | 125 | is_superuser: account.is_superuser, |
| 129 | password_change_required: account.password_change_required, | 126 | password_change_required: account.password_change_required, |
| 130 | instances, | 127 | instances, |
| 131 | has_active, | ||
| 132 | }; | 128 | }; |
| 133 | 129 | ||
| 134 | Ok(Html(template.render().unwrap_or_default())) | 130 | Ok(Html(template.render().unwrap_or_default())) |
| @@ -283,7 +279,6 @@ async fn edit_form( | |||
| 283 | instance, | 279 | instance, |
| 284 | current_seed, | 280 | current_seed, |
| 285 | max_memory_mb: state.config.max_memory_mb, | 281 | max_memory_mb: state.config.max_memory_mb, |
| 286 | error: None, | ||
| 287 | }; | 282 | }; |
| 288 | 283 | ||
| 289 | Ok(Html(template.render().unwrap_or_default())) | 284 | Ok(Html(template.render().unwrap_or_default())) |
| @@ -428,6 +423,7 @@ async fn activate_instance( | |||
| 428 | // Pull image + start container in background so the UI stays responsive | 423 | // Pull image + start container in background so the UI stays responsive |
| 429 | let docker = state.docker.clone(); | 424 | let docker = state.docker.clone(); |
| 430 | let db = state.db.clone(); | 425 | let db = state.db.clone(); |
| 426 | let rcon_pw = instance.rcon_password.clone(); | ||
| 431 | tokio::spawn(async move { | 427 | tokio::spawn(async move { |
| 432 | { | 428 | { |
| 433 | let conn = db.conn(); | 429 | let conn = db.conn(); |
| @@ -439,9 +435,33 @@ async fn activate_instance( | |||
| 439 | } | 435 | } |
| 440 | match docker.start_container(&instance).await { | 436 | match docker.start_container(&instance).await { |
| 441 | Ok(()) => { | 437 | Ok(()) => { |
| 438 | { | ||
| 439 | let conn = db.conn(); | ||
| 440 | conn.execute( | ||
| 441 | "UPDATE instances SET container_state = 'booting' WHERE is_active = 1", | ||
| 442 | [], | ||
| 443 | ) | ||
| 444 | .ok(); | ||
| 445 | } | ||
| 446 | // Wait for Minecraft to be ready via RCON | ||
| 447 | let rcon = crate::rcon::RconClient::new(rcon_pw); | ||
| 448 | for _ in 0..30 { | ||
| 449 | tokio::time::sleep(std::time::Duration::from_secs(2)).await; | ||
| 450 | if rcon.send_command_async("list".into()).await.is_ok() { | ||
| 451 | let conn = db.conn(); | ||
| 452 | conn.execute( | ||
| 453 | "UPDATE instances SET container_state = 'running' WHERE is_active = 1", | ||
| 454 | [], | ||
| 455 | ) | ||
| 456 | .ok(); | ||
| 457 | tracing::info!("Server is ready (RCON responded)"); | ||
| 458 | return; | ||
| 459 | } | ||
| 460 | } | ||
| 461 | tracing::error!("Server did not become ready within 60 seconds"); | ||
| 442 | let conn = db.conn(); | 462 | let conn = db.conn(); |
| 443 | conn.execute( | 463 | conn.execute( |
| 444 | "UPDATE instances SET container_state = 'running' WHERE is_active = 1", | 464 | "UPDATE instances SET container_state = 'error' WHERE is_active = 1", |
| 445 | [], | 465 | [], |
| 446 | ) | 466 | ) |
| 447 | .ok(); | 467 | .ok(); |
| @@ -458,7 +478,7 @@ async fn activate_instance( | |||
| 458 | } | 478 | } |
| 459 | }); | 479 | }); |
| 460 | 480 | ||
| 461 | Ok(Redirect::to("/")) | 481 | Ok(Redirect::to("/instances")) |
| 462 | } | 482 | } |
| 463 | 483 | ||
| 464 | async fn deactivate_instance( | 484 | async fn deactivate_instance( |
| @@ -475,7 +495,7 @@ async fn deactivate_instance( | |||
| 475 | .ok(); | 495 | .ok(); |
| 476 | drop(conn); | 496 | drop(conn); |
| 477 | 497 | ||
| 478 | Ok(Redirect::to("/")) | 498 | Ok(Redirect::to("/instances")) |
| 479 | } | 499 | } |
| 480 | 500 | ||
| 481 | fn generate_rcon_password() -> String { | 501 | fn generate_rcon_password() -> String { |
