feat: implement Phase 5 Resource Registry & Heartbeat
This commit is contained in:
@@ -8,7 +8,7 @@ use axum::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::core::db::{Database, PostgresDb};
|
||||
use crate::core::db::{Database, PostgresDb, ResourceRecord};
|
||||
|
||||
pub fn identity_routes() -> Router<crate::api::server::AppState> {
|
||||
Router::new()
|
||||
@@ -19,6 +19,9 @@ pub fn identity_routes() -> Router<crate::api::server::AppState> {
|
||||
.route("/api/v1/people/{identity_id}/reject-candidate", post(reject_candidate))
|
||||
.route("/api/v1/files", get(list_files))
|
||||
.route("/api/v1/files/{uuid}", get(get_file_detail))
|
||||
.route("/api/v1/resources/register", post(register_resource))
|
||||
.route("/api/v1/resources/heartbeat", post(heartbeat_resource))
|
||||
.route("/api/v1/resources", get(list_resources))
|
||||
}
|
||||
|
||||
// ... (Keep existing functions) ...
|
||||
@@ -277,3 +280,101 @@ async fn get_file_detail(
|
||||
metadata: serde_json::json!({}),
|
||||
}))
|
||||
}
|
||||
|
||||
// --- Resource Registry Endpoints (Phase 5) ---
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct RegisterResourceRequest {
|
||||
pub resource_id: String,
|
||||
pub resource_type: String,
|
||||
pub category: String,
|
||||
pub capabilities: Option<serde_json::Value>,
|
||||
pub config: Option<serde_json::Value>,
|
||||
pub metadata: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ResourceResponse {
|
||||
pub success: bool,
|
||||
pub message: String,
|
||||
pub data: Option<ResourceItem>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ResourceItem {
|
||||
pub resource_id: String,
|
||||
pub resource_type: String,
|
||||
pub category: String,
|
||||
pub capabilities: Option<serde_json::Value>,
|
||||
pub status: String,
|
||||
pub last_heartbeat: Option<chrono::DateTime<chrono::Utc>>,
|
||||
}
|
||||
|
||||
async fn register_resource(
|
||||
State(state): State<crate::api::server::AppState>,
|
||||
Json(req): Json<RegisterResourceRequest>,
|
||||
) -> Result<Json<ResourceResponse>, (StatusCode, String)> {
|
||||
let resource = ResourceRecord {
|
||||
resource_id: req.resource_id.clone(),
|
||||
resource_type: req.resource_type.clone(),
|
||||
category: req.category.clone(),
|
||||
capabilities: req.capabilities,
|
||||
config: req.config,
|
||||
metadata: req.metadata,
|
||||
status: "online".to_string(),
|
||||
last_heartbeat: None,
|
||||
created_at: None,
|
||||
};
|
||||
|
||||
state.db.register_resource(resource).await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
Ok(Json(ResourceResponse {
|
||||
success: true,
|
||||
message: "Resource registered successfully".to_string(),
|
||||
data: None, // We could return the full record, but simplified for now
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct HeartbeatRequest {
|
||||
pub resource_id: String,
|
||||
pub status: Option<String>,
|
||||
}
|
||||
|
||||
async fn heartbeat_resource(
|
||||
State(state): State<crate::api::server::AppState>,
|
||||
Json(req): Json<HeartbeatRequest>,
|
||||
) -> Result<Json<ResourceResponse>, (StatusCode, String)> {
|
||||
let status = req.status.unwrap_or("online".to_string());
|
||||
state.db.heartbeat_resource(&req.resource_id, &status).await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
Ok(Json(ResourceResponse {
|
||||
success: true,
|
||||
message: "Heartbeat received".to_string(),
|
||||
data: None,
|
||||
}))
|
||||
}
|
||||
|
||||
async fn list_resources(
|
||||
State(state): State<crate::api::server::AppState>,
|
||||
) -> Result<Json<ResourceResponse>, (StatusCode, String)> {
|
||||
let records = state.db.list_resources().await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
let data: Vec<ResourceItem> = records.into_iter().map(|r| ResourceItem {
|
||||
resource_id: r.resource_id,
|
||||
resource_type: r.resource_type,
|
||||
category: r.category,
|
||||
capabilities: r.capabilities,
|
||||
status: r.status,
|
||||
last_heartbeat: r.last_heartbeat,
|
||||
}).collect();
|
||||
|
||||
Ok(Json(ResourceResponse {
|
||||
success: true,
|
||||
message: "Resources listed".to_string(),
|
||||
data: None,
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user