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