Line data Source code
1 : //! Structs representing the JSON formats used in the compute_ctl's HTTP API.
2 :
3 : use std::fmt::Display;
4 :
5 : use chrono::{DateTime, Utc};
6 : use jsonwebtoken::jwk::JwkSet;
7 : use serde::{Deserialize, Serialize, Serializer};
8 :
9 : use crate::{
10 : privilege::Privilege,
11 : spec::{ComputeSpec, Database, ExtVersion, PgIdent, Role},
12 : };
13 :
14 0 : #[derive(Serialize, Debug, Deserialize)]
15 : pub struct GenericAPIError {
16 : pub error: String,
17 : }
18 :
19 : #[derive(Debug, Clone, Serialize)]
20 : pub struct ExtensionInstallResponse {
21 : pub extension: PgIdent,
22 : pub version: ExtVersion,
23 : }
24 :
25 : /// Response of the /status API
26 0 : #[derive(Serialize, Debug, Deserialize)]
27 : #[serde(rename_all = "snake_case")]
28 : pub struct ComputeStatusResponse {
29 : pub start_time: DateTime<Utc>,
30 : pub tenant: Option<String>,
31 : pub timeline: Option<String>,
32 : pub status: ComputeStatus,
33 : #[serde(serialize_with = "rfc3339_serialize")]
34 : pub last_active: Option<DateTime<Utc>>,
35 : pub error: Option<String>,
36 : }
37 :
38 0 : #[derive(Serialize, Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
39 : #[serde(rename_all = "snake_case")]
40 : pub enum ComputeStatus {
41 : // Spec wasn't provided at start, waiting for it to be
42 : // provided by control-plane.
43 : Empty,
44 : // Compute configuration was requested.
45 : ConfigurationPending,
46 : // Compute node has spec and initial startup and
47 : // configuration is in progress.
48 : Init,
49 : // Compute is configured and running.
50 : Running,
51 : // New spec is being applied.
52 : Configuration,
53 : // Either startup or configuration failed,
54 : // compute will exit soon or is waiting for
55 : // control-plane to terminate it.
56 : Failed,
57 : // Termination requested
58 : TerminationPending,
59 : // Terminated Postgres
60 : Terminated,
61 : }
62 :
63 : impl Display for ComputeStatus {
64 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 0 : match self {
66 0 : ComputeStatus::Empty => f.write_str("empty"),
67 0 : ComputeStatus::ConfigurationPending => f.write_str("configuration-pending"),
68 0 : ComputeStatus::Init => f.write_str("init"),
69 0 : ComputeStatus::Running => f.write_str("running"),
70 0 : ComputeStatus::Configuration => f.write_str("configuration"),
71 0 : ComputeStatus::Failed => f.write_str("failed"),
72 0 : ComputeStatus::TerminationPending => f.write_str("termination-pending"),
73 0 : ComputeStatus::Terminated => f.write_str("terminated"),
74 : }
75 0 : }
76 : }
77 :
78 0 : pub fn rfc3339_serialize<S>(x: &Option<DateTime<Utc>>, s: S) -> Result<S::Ok, S::Error>
79 0 : where
80 0 : S: Serializer,
81 0 : {
82 0 : if let Some(x) = x {
83 0 : x.to_rfc3339().serialize(s)
84 : } else {
85 0 : s.serialize_none()
86 : }
87 0 : }
88 :
89 : /// Response of the /metrics.json API
90 : #[derive(Clone, Debug, Default, Serialize)]
91 : pub struct ComputeMetrics {
92 : /// Time spent waiting in pool
93 : pub wait_for_spec_ms: u64,
94 :
95 : /// Time spent checking if safekeepers are synced
96 : pub sync_sk_check_ms: u64,
97 :
98 : /// Time spent syncing safekeepers (walproposer.c).
99 : /// In most cases this should be zero.
100 : pub sync_safekeepers_ms: u64,
101 :
102 : /// Time it took to establish a pg connection to the pageserver.
103 : /// This is two roundtrips, so it's a good proxy for compute-pageserver
104 : /// latency. The latency is usually 0.2ms, but it's not safe to assume
105 : /// that.
106 : pub pageserver_connect_micros: u64,
107 :
108 : /// Time to get basebackup from pageserver and write it to disk.
109 : pub basebackup_ms: u64,
110 :
111 : /// Compressed size of basebackup received.
112 : pub basebackup_bytes: u64,
113 :
114 : /// Time spent starting potgres. This includes initialization of shared
115 : /// buffers, preloading extensions, and other pg operations.
116 : pub start_postgres_ms: u64,
117 :
118 : /// Time spent applying pg catalog updates that were made in the console
119 : /// UI. This should be 0 when startup time matters, since cplane tries
120 : /// to do these updates eagerly, and passes the skip_pg_catalog_updates
121 : /// when it's safe to skip this step.
122 : pub config_ms: u64,
123 :
124 : /// Total time, from when we receive the spec to when we're ready to take
125 : /// pg connections.
126 : pub total_startup_ms: u64,
127 : pub load_ext_ms: u64,
128 : pub num_ext_downloaded: u64,
129 : pub largest_ext_size: u64, // these are measured in bytes
130 : pub total_ext_download_size: u64,
131 : }
132 :
133 : #[derive(Clone, Debug, Default, Serialize)]
134 : pub struct CatalogObjects {
135 : pub roles: Vec<Role>,
136 : pub databases: Vec<Database>,
137 : }
138 :
139 0 : #[derive(Debug, Deserialize, Serialize)]
140 : pub struct ComputeCtlConfig {
141 : pub jwks: JwkSet,
142 : }
143 :
144 : impl Default for ComputeCtlConfig {
145 0 : fn default() -> Self {
146 0 : Self {
147 0 : jwks: JwkSet {
148 0 : keys: Vec::default(),
149 0 : },
150 0 : }
151 0 : }
152 : }
153 :
154 : /// Response of the `/computes/{compute_id}/spec` control-plane API.
155 0 : #[derive(Deserialize, Debug)]
156 : pub struct ControlPlaneSpecResponse {
157 : pub spec: Option<ComputeSpec>,
158 : pub status: ControlPlaneComputeStatus,
159 : pub compute_ctl_config: ComputeCtlConfig,
160 : }
161 :
162 0 : #[derive(Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
163 : #[serde(rename_all = "snake_case")]
164 : pub enum ControlPlaneComputeStatus {
165 : // Compute is known to control-plane, but it's not
166 : // yet attached to any timeline / endpoint.
167 : Empty,
168 : // Compute is attached to some timeline / endpoint and
169 : // should be able to start with provided spec.
170 : Attached,
171 : }
172 :
173 : #[derive(Clone, Debug, Default, Serialize)]
174 : pub struct InstalledExtension {
175 : pub extname: String,
176 : pub version: String,
177 : pub n_databases: u32, // Number of databases using this extension
178 : pub owned_by_superuser: String,
179 : }
180 :
181 : #[derive(Clone, Debug, Default, Serialize)]
182 : pub struct InstalledExtensions {
183 : pub extensions: Vec<InstalledExtension>,
184 : }
185 :
186 : #[derive(Clone, Debug, Default, Serialize)]
187 : pub struct ExtensionInstallResult {
188 : pub extension: PgIdent,
189 : pub version: ExtVersion,
190 : }
191 : #[derive(Clone, Debug, Default, Serialize)]
192 : pub struct SetRoleGrantsResponse {
193 : pub database: PgIdent,
194 : pub schema: PgIdent,
195 : pub privileges: Vec<Privilege>,
196 : pub role: PgIdent,
197 : }
|