koprogo_api/application/ports/
grid_participation_port.rs1use async_trait::async_trait;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct GridTaskId(pub String);
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
13pub enum GridTaskKind {
14 EnergyGroupOptimisation {
16 building_id: Uuid,
17 anonymised_readings_json: String,
19 simulation_months: u32,
20 },
21 BuildingThermalSimulation {
23 building_id: Uuid,
24 insulation_score: f64,
25 surface_m2: f64,
26 heating_degree_days: f64,
27 },
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct GridTask {
33 pub internal_id: Uuid,
35 pub copropriete_id: Uuid,
37 pub organization_id: Uuid,
39 pub kind: GridTaskKind,
41 pub priority: u8,
43 pub deadline: DateTime<Utc>,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
49pub enum GridTaskStatus {
50 Queued,
52 Running { started_at: DateTime<Utc> },
54 Completed {
56 completed_at: DateTime<Utc>,
57 result_json: String,
59 },
60 Failed {
62 failed_at: DateTime<Utc>,
63 reason: String,
64 },
65 Cancelled,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct BoincConsent {
72 pub owner_id: Uuid,
73 pub organization_id: Uuid,
74 pub granted: bool,
75 pub granted_at: Option<DateTime<Utc>>,
76 pub revoked_at: Option<DateTime<Utc>>,
77 pub consent_ip: Option<String>,
79 pub consent_version: String,
81}
82
83#[derive(Debug, thiserror::Error)]
85pub enum GridError {
86 #[error("Consent not granted for owner {0}")]
87 ConsentNotGranted(Uuid),
88
89 #[error("BOINC RPC failed: {0}")]
90 RpcFailed(String),
91
92 #[error("Task not found: {0}")]
93 TaskNotFound(String),
94
95 #[error("K-anonymity constraint violated: minimum {min} participants required, got {got}")]
96 KAnonymityViolated { min: usize, got: usize },
97
98 #[error("Process error: {0}")]
99 ProcessError(String),
100
101 #[error("Result parse error: {0}")]
102 ResultParseError(String),
103}
104
105#[async_trait]
112pub trait GridParticipationPort: Send + Sync {
113 async fn check_consent(&self, owner_id: Uuid) -> Result<bool, GridError>;
117
118 async fn get_consent(&self, owner_id: Uuid) -> Result<Option<BoincConsent>, GridError>;
120
121 async fn grant_consent(
123 &self,
124 owner_id: Uuid,
125 organization_id: Uuid,
126 consent_version: &str,
127 consent_ip: Option<&str>,
128 ) -> Result<BoincConsent, GridError>;
129
130 async fn revoke_consent(&self, owner_id: Uuid) -> Result<(), GridError>;
132
133 async fn submit_task(&self, task: GridTask) -> Result<GridTaskId, GridError>;
138
139 async fn poll_result(&self, task_id: &GridTaskId) -> Result<GridTaskStatus, GridError>;
141
142 async fn cancel_task(&self, task_id: &GridTaskId) -> Result<(), GridError>;
144}