huskies: merge 775

This commit is contained in:
dave
2026-04-28 12:19:49 +00:00
parent e9ed58502a
commit b7db6d6aae
10 changed files with 139 additions and 46 deletions
+12 -2
View File
@@ -117,14 +117,19 @@ pub struct GatewayState {
impl GatewayState {
/// Create a new gateway state from a config and config directory.
///
/// The first project in the config becomes the active project by default.
/// The active project is restored from the CRDT `gateway_config.active_project`
/// register when available. Falls back to the first project in the config.
/// Agent registrations are stored in the CRDT nodes collection.
pub fn new(
gateway_config: GatewayConfig,
config_dir: PathBuf,
port: u16,
) -> Result<Self, String> {
let first = config::validate_config(&gateway_config)?;
let first_from_config = config::validate_config(&gateway_config)?;
// Restore active project from CRDT if the stored value is still valid.
let first = crate::crdt_state::read_gateway_active_project()
.filter(|p| gateway_config.projects.contains_key(p))
.unwrap_or(first_from_config);
let (event_tx, _) = tokio::sync::broadcast::channel(EVENT_CHANNEL_CAPACITY);
Ok(Self {
projects: Arc::new(RwLock::new(gateway_config.projects)),
@@ -155,6 +160,10 @@ impl GatewayState {
// ── Public API ──────────────────────────────────────────────────────────────
/// Switch the active project. Returns the project's URL on success.
///
/// Writes the new active project to the CRDT `gateway_config.active_project`
/// register (LWW — last write wins) so the selection is persisted across
/// restarts and replicated to connected peers.
pub async fn switch_project(state: &GatewayState, project: &str) -> Result<String, Error> {
if project.is_empty() {
return Err(Error::Config("missing required parameter: project".into()));
@@ -166,6 +175,7 @@ pub async fn switch_project(state: &GatewayState, project: &str) -> Result<Strin
};
*state.active_project.write().await = project.to_string();
crate::crdt_state::write_gateway_active_project(project);
Ok(url)
}