Enhance development workflow and deployment practices for Archipelago
- Updated the Development-Workflow documentation to clarify deployment strategy, emphasizing direct deployment to the live system for testing. - Added detailed instructions for the deployment command, including syncing code, building frontend and backend, and restarting services. - Improved SSH key management section to assist with authentication issues. - Expanded the testing workflow to include steps for checking logs and syncing changes back to the ISO build. - Updated the ISO build integration section to ensure system-level changes are captured for future builds. - Refactored various sections for clarity and completeness, including deployment paths and system configuration files.
This commit is contained in:
@@ -6,6 +6,7 @@ use futures_util::{SinkExt, StreamExt};
|
||||
use hyper::{Method, Request, Response, StatusCode};
|
||||
use hyper_ws_listener::WsStream;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::broadcast;
|
||||
use tokio_tungstenite::tungstenite::Message;
|
||||
use tracing::{debug, info};
|
||||
|
||||
@@ -94,11 +95,14 @@ impl ApiHandler {
|
||||
debug!("Sent initial data dump at revision {}", initial_msg.rev);
|
||||
}
|
||||
|
||||
// Subscribe to state updates
|
||||
let mut state_rx = state_manager.subscribe();
|
||||
|
||||
// Send periodic pings to keep connection alive
|
||||
let ping_interval = tokio::time::interval(tokio::time::Duration::from_secs(30));
|
||||
tokio::pin!(ping_interval);
|
||||
|
||||
// Keep connection open; UI may send/receive JSON patches. For now just accept and ignore.
|
||||
// Keep connection open and forward state updates to client
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = ping_interval.tick() => {
|
||||
@@ -107,6 +111,28 @@ impl ApiHandler {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Forward state updates from broadcast channel to WebSocket
|
||||
update = state_rx.recv() => {
|
||||
match update {
|
||||
Ok(msg) => {
|
||||
if let Ok(json_msg) = serde_json::to_string(&msg) {
|
||||
if let Err(e) = tx.send(Message::Text(json_msg)).await {
|
||||
debug!("Failed to send state update: {}", e);
|
||||
break;
|
||||
}
|
||||
debug!("Sent state update at revision {}", msg.rev);
|
||||
}
|
||||
}
|
||||
Err(broadcast::error::RecvError::Lagged(skipped)) => {
|
||||
debug!("Client lagged behind, skipped {} messages", skipped);
|
||||
// Continue receiving - the client will get the next update
|
||||
}
|
||||
Err(broadcast::error::RecvError::Closed) => {
|
||||
debug!("Broadcast channel closed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
msg = rx.next() => {
|
||||
match msg {
|
||||
Some(Ok(Message::Close(_))) => break,
|
||||
|
||||
@@ -445,15 +445,30 @@ impl RpcHandler {
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing package id"))?;
|
||||
|
||||
// Convert package ID to container name (e.g., "bitcoin" -> "archy-bitcoin")
|
||||
let container_name = format!("archy-{}", package_id);
|
||||
|
||||
// Use docker CLI to start the container
|
||||
let output = tokio::process::Command::new("docker")
|
||||
.arg("start")
|
||||
.arg(&container_name)
|
||||
// But also check if container exists without the prefix
|
||||
let container_name = if let Ok(output) = tokio::process::Command::new("sudo")
|
||||
.args(["podman", "ps", "-a", "--format", "{{.Names}}", "--filter", &format!("name=^{}$", package_id)])
|
||||
.output()
|
||||
.await
|
||||
.context("Failed to execute docker start")?;
|
||||
{
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
if !stdout.trim().is_empty() {
|
||||
debug!("Found container without prefix: {}", package_id);
|
||||
package_id.to_string()
|
||||
} else {
|
||||
debug!("Using archy- prefix: archy-{}", package_id);
|
||||
format!("archy-{}", package_id)
|
||||
}
|
||||
} else {
|
||||
format!("archy-{}", package_id)
|
||||
};
|
||||
|
||||
// Use podman CLI to start the container
|
||||
let output = tokio::process::Command::new("sudo")
|
||||
.args(["podman", "start", &container_name])
|
||||
.output()
|
||||
.await
|
||||
.context("Failed to execute podman start")?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
@@ -474,15 +489,29 @@ impl RpcHandler {
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing package id"))?;
|
||||
|
||||
// Convert package ID to container name
|
||||
let container_name = format!("archy-{}", package_id);
|
||||
|
||||
// Use docker CLI to stop the container
|
||||
let output = tokio::process::Command::new("docker")
|
||||
.arg("stop")
|
||||
.arg(&container_name)
|
||||
let container_name = if let Ok(output) = tokio::process::Command::new("sudo")
|
||||
.args(["podman", "ps", "-a", "--format", "{{.Names}}", "--filter", &format!("name=^{}$", package_id)])
|
||||
.output()
|
||||
.await
|
||||
.context("Failed to execute docker stop")?;
|
||||
{
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
if !stdout.trim().is_empty() {
|
||||
debug!("Found container without prefix: {}", package_id);
|
||||
package_id.to_string()
|
||||
} else {
|
||||
debug!("Using archy- prefix: archy-{}", package_id);
|
||||
format!("archy-{}", package_id)
|
||||
}
|
||||
} else {
|
||||
format!("archy-{}", package_id)
|
||||
};
|
||||
|
||||
// Use podman CLI to stop the container
|
||||
let output = tokio::process::Command::new("sudo")
|
||||
.args(["podman", "stop", &container_name])
|
||||
.output()
|
||||
.await
|
||||
.context("Failed to execute podman stop")?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
@@ -503,15 +532,29 @@ impl RpcHandler {
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing package id"))?;
|
||||
|
||||
// Convert package ID to container name
|
||||
let container_name = format!("archy-{}", package_id);
|
||||
|
||||
// Use docker CLI to restart the container
|
||||
let output = tokio::process::Command::new("docker")
|
||||
.arg("restart")
|
||||
.arg(&container_name)
|
||||
let container_name = if let Ok(output) = tokio::process::Command::new("sudo")
|
||||
.args(["podman", "ps", "-a", "--format", "{{.Names}}", "--filter", &format!("name=^{}$", package_id)])
|
||||
.output()
|
||||
.await
|
||||
.context("Failed to execute docker restart")?;
|
||||
{
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
if !stdout.trim().is_empty() {
|
||||
debug!("Found container without prefix: {}", package_id);
|
||||
package_id.to_string()
|
||||
} else {
|
||||
debug!("Using archy- prefix: archy-{}", package_id);
|
||||
format!("archy-{}", package_id)
|
||||
}
|
||||
} else {
|
||||
format!("archy-{}", package_id)
|
||||
};
|
||||
|
||||
// Use podman CLI to restart the container
|
||||
let output = tokio::process::Command::new("sudo")
|
||||
.args(["podman", "restart", &container_name])
|
||||
.output()
|
||||
.await
|
||||
.context("Failed to execute podman restart")?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
|
||||
Reference in New Issue
Block a user