1use std::collections::BTreeMap;
5
6use async_graphql::{scalar, Request, Response, SimpleObject};
7use linera_sdk_derive::GraphQLMutationRootInCrate;
8use serde::{Deserialize, Serialize};
9
10use crate::linera_base_types::{
11 AccountOwner, ApplicationId, ChainId, ContractAbi, DataBlobHash, MessagePolicy, ServiceAbi,
12};
13
14pub struct ControllerAbi;
15
16impl ContractAbi for ControllerAbi {
17 type Operation = Operation;
18 type Response = ();
19}
20
21impl ServiceAbi for ControllerAbi {
22 type Query = Request;
23 type QueryResponse = Response;
24}
25
26pub type ManagedServiceId = DataBlobHash;
28
29#[derive(Debug, Deserialize, Serialize, GraphQLMutationRootInCrate)]
30pub enum Operation {
31 ExecuteWorkerCommand {
33 owner: AccountOwner,
34 command: WorkerCommand,
35 },
36 ExecuteControllerCommand {
38 admin: AccountOwner,
39 command: ControllerCommand,
40 },
41}
42
43#[derive(Clone, Debug, Deserialize, Serialize)]
45pub enum WorkerCommand {
46 RegisterWorker { capabilities: Vec<String> },
48 DeregisterWorker,
50}
51
52scalar!(WorkerCommand);
53
54#[derive(Clone, Debug, Deserialize, Serialize)]
56pub enum ControllerCommand {
57 SetAdmins { admins: Option<Vec<AccountOwner>> },
59 RemoveWorker { worker_id: ChainId },
62 UpdateService {
64 service_id: ManagedServiceId,
65 workers: Vec<ChainId>,
66 },
67 RemoveService { service_id: ManagedServiceId },
69 UpdateAllServices {
71 services: Vec<(ManagedServiceId, Vec<ChainId>)>,
72 },
73 UpdateChain {
75 chain_id: ChainId,
76 workers: Vec<ChainId>,
77 },
78 RemoveChain { chain_id: ChainId },
80 UpdateAllChains {
82 chains: Vec<(ChainId, Vec<ChainId>)>,
83 },
84}
85
86scalar!(ControllerCommand);
87
88#[derive(Clone, Debug, Serialize, Deserialize, SimpleObject)]
90pub struct Worker {
91 pub owner: AccountOwner,
93 pub capabilities: Vec<String>,
96}
97
98#[derive(Clone, Debug, Serialize, Deserialize)]
100pub struct ManagedService {
101 pub application_id: ApplicationId,
103 pub name: String,
106 pub chain_id: ChainId,
110 pub requirements: Vec<String>,
113}
114
115scalar!(ManagedService);
116
117#[derive(Clone, Debug, Deserialize, Serialize)]
120pub struct LocalWorkerState {
121 pub local_worker: Option<Worker>,
123 pub local_services: Vec<ManagedService>,
125 pub local_chains: Vec<ChainId>,
128 pub local_message_policy: BTreeMap<ChainId, MessagePolicy>,
130}
131
132scalar!(LocalWorkerState);
133
134#[derive(Clone, Debug, Deserialize, Serialize, GraphQLMutationRootInCrate)]
136pub enum Message {
137 ExecuteWorkerCommand {
139 owner: AccountOwner,
140 command: WorkerCommand,
141 },
142 ExecuteControllerCommand {
143 admin: AccountOwner,
144 command: ControllerCommand,
145 },
146 Reset,
148 Start {
149 service_id: ManagedServiceId,
150 },
151 Stop {
152 service_id: ManagedServiceId,
153 },
154 FollowChain {
155 chain_id: ChainId,
156 },
157 ForgetChain {
158 chain_id: ChainId,
159 },
160}
161
162#[cfg(not(target_arch = "wasm32"))]
163pub mod formats {
164 use serde_reflection::{Samples, Tracer, TracerConfig};
165
166 use super::{
167 ControllerAbi, ControllerCommand, ManagedServiceId, Message, Operation, Worker,
168 WorkerCommand,
169 };
170 use crate::{
171 formats::{BcsApplication, Formats},
172 linera_base_types::AccountOwner,
173 };
174
175 pub struct ControllerApplication;
177
178 impl BcsApplication for ControllerApplication {
179 type Abi = ControllerAbi;
180
181 fn formats() -> serde_reflection::Result<Formats> {
182 let mut tracer = Tracer::new(
183 TracerConfig::default()
184 .record_samples_for_newtype_structs(true)
185 .record_samples_for_tuple_structs(true),
186 );
187 let samples = Samples::new();
188
189 let (operation, _) = tracer.trace_type::<Operation>(&samples)?;
191 let (response, _) = tracer.trace_type::<()>(&samples)?;
192 let (message, _) = tracer.trace_type::<Message>(&samples)?;
193 let (event_value, _) = tracer.trace_type::<()>(&samples)?;
194
195 tracer.trace_type::<WorkerCommand>(&samples)?;
197 tracer.trace_type::<ControllerCommand>(&samples)?;
198 tracer.trace_type::<Worker>(&samples)?;
199 tracer.trace_type::<ManagedServiceId>(&samples)?;
200 tracer.trace_type::<AccountOwner>(&samples)?;
201
202 let registry = tracer.registry()?;
203
204 Ok(Formats {
205 registry,
206 operation,
207 response,
208 message,
209 event_value,
210 })
211 }
212 }
213}