Line data Source code
1 : //! Types used in safekeeper http API. Many of them are also reused internally.
2 :
3 : use std::net::SocketAddr;
4 :
5 : use pageserver_api::shard::ShardIdentity;
6 : use postgres_ffi::TimestampTz;
7 : use serde::{Deserialize, Serialize};
8 : use tokio::time::Instant;
9 : use utils::id::{NodeId, TenantId, TenantTimelineId, TimelineId};
10 : use utils::lsn::Lsn;
11 : use utils::pageserver_feedback::PageserverFeedback;
12 :
13 : use crate::membership::Configuration;
14 : use crate::{ServerInfo, Term};
15 :
16 : #[derive(Debug, Serialize)]
17 : pub struct SafekeeperStatus {
18 : pub id: NodeId,
19 : }
20 :
21 0 : #[derive(Serialize, Deserialize, Clone)]
22 : pub struct TimelineCreateRequest {
23 : pub tenant_id: TenantId,
24 : pub timeline_id: TimelineId,
25 : pub mconf: Configuration,
26 : /// In the PG_VERSION_NUM macro format, like 140017.
27 : pub pg_version: u32,
28 : pub system_id: Option<u64>,
29 : // By default WAL_SEGMENT_SIZE
30 : pub wal_seg_size: Option<u32>,
31 : pub start_lsn: Lsn,
32 : // Normal creation should omit this field (start_lsn initializes all LSNs).
33 : // However, we allow specifying custom value higher than start_lsn for
34 : // manual recovery case, see test_s3_wal_replay.
35 : pub commit_lsn: Option<Lsn>,
36 : }
37 :
38 : /// Same as TermLsn, but serializes LSN using display serializer
39 : /// in Postgres format, i.e. 0/FFFFFFFF. Used only for the API response.
40 0 : #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
41 : pub struct TermSwitchApiEntry {
42 : pub term: Term,
43 : pub lsn: Lsn,
44 : }
45 :
46 : /// Augment AcceptorState with last_log_term for convenience
47 0 : #[derive(Debug, Serialize, Deserialize)]
48 : pub struct AcceptorStateStatus {
49 : pub term: Term,
50 : pub epoch: Term, // aka last_log_term, old `epoch` name is left for compatibility
51 : pub term_history: Vec<TermSwitchApiEntry>,
52 : }
53 :
54 : /// Things safekeeper should know about timeline state on peers.
55 : /// Used as both model and internally.
56 0 : #[derive(Debug, Clone, Serialize, Deserialize)]
57 : pub struct PeerInfo {
58 : pub sk_id: NodeId,
59 : pub term: Term,
60 : /// Term of the last entry.
61 : pub last_log_term: Term,
62 : /// LSN of the last record.
63 : pub flush_lsn: Lsn,
64 : pub commit_lsn: Lsn,
65 : /// Since which LSN safekeeper has WAL.
66 : pub local_start_lsn: Lsn,
67 : /// When info was received. Serde annotations are not very useful but make
68 : /// the code compile -- we don't rely on this field externally.
69 : #[serde(skip)]
70 : #[serde(default = "Instant::now")]
71 : pub ts: Instant,
72 : pub pg_connstr: String,
73 : pub http_connstr: String,
74 : pub https_connstr: Option<String>,
75 : }
76 :
77 : pub type FullTransactionId = u64;
78 :
79 : /// Hot standby feedback received from replica
80 0 : #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
81 : pub struct HotStandbyFeedback {
82 : pub ts: TimestampTz,
83 : pub xmin: FullTransactionId,
84 : pub catalog_xmin: FullTransactionId,
85 : }
86 :
87 : pub const INVALID_FULL_TRANSACTION_ID: FullTransactionId = 0;
88 :
89 : impl HotStandbyFeedback {
90 2578 : pub fn empty() -> HotStandbyFeedback {
91 2578 : HotStandbyFeedback {
92 2578 : ts: 0,
93 2578 : xmin: 0,
94 2578 : catalog_xmin: 0,
95 2578 : }
96 2578 : }
97 : }
98 :
99 : /// Standby status update
100 0 : #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
101 : pub struct StandbyReply {
102 : pub write_lsn: Lsn, // The location of the last WAL byte + 1 received and written to disk in the standby.
103 : pub flush_lsn: Lsn, // The location of the last WAL byte + 1 flushed to disk in the standby.
104 : pub apply_lsn: Lsn, // The location of the last WAL byte + 1 applied in the standby.
105 : pub reply_ts: TimestampTz, // The client's system clock at the time of transmission, as microseconds since midnight on 2000-01-01.
106 : pub reply_requested: bool,
107 : }
108 :
109 : impl StandbyReply {
110 13 : pub fn empty() -> Self {
111 13 : StandbyReply {
112 13 : write_lsn: Lsn::INVALID,
113 13 : flush_lsn: Lsn::INVALID,
114 13 : apply_lsn: Lsn::INVALID,
115 13 : reply_ts: 0,
116 13 : reply_requested: false,
117 13 : }
118 13 : }
119 : }
120 :
121 0 : #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
122 : pub struct StandbyFeedback {
123 : pub reply: StandbyReply,
124 : pub hs_feedback: HotStandbyFeedback,
125 : }
126 :
127 : impl StandbyFeedback {
128 7 : pub fn empty() -> Self {
129 7 : StandbyFeedback {
130 7 : reply: StandbyReply::empty(),
131 7 : hs_feedback: HotStandbyFeedback::empty(),
132 7 : }
133 7 : }
134 : }
135 :
136 : /// Receiver is either pageserver or regular standby, which have different
137 : /// feedbacks.
138 : /// Used as both model and internally.
139 0 : #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
140 : pub enum ReplicationFeedback {
141 : Pageserver(PageserverFeedback),
142 : Standby(StandbyFeedback),
143 : }
144 :
145 : /// Uniquely identifies a WAL service connection. Logged in spans for
146 : /// observability.
147 : pub type ConnectionId = u32;
148 :
149 : /// Serialize is used only for json'ing in API response. Also used internally.
150 0 : #[derive(Debug, Clone, Serialize, Deserialize)]
151 : pub enum WalSenderState {
152 : Vanilla(VanillaWalSenderState),
153 : Interpreted(InterpretedWalSenderState),
154 : }
155 :
156 0 : #[derive(Debug, Clone, Serialize, Deserialize)]
157 : pub struct VanillaWalSenderState {
158 : pub ttid: TenantTimelineId,
159 : pub addr: SocketAddr,
160 : pub conn_id: ConnectionId,
161 : // postgres application_name
162 : pub appname: Option<String>,
163 : pub feedback: ReplicationFeedback,
164 : }
165 :
166 0 : #[derive(Debug, Clone, Serialize, Deserialize)]
167 : pub struct InterpretedWalSenderState {
168 : pub ttid: TenantTimelineId,
169 : pub shard: ShardIdentity,
170 : pub addr: SocketAddr,
171 : pub conn_id: ConnectionId,
172 : // postgres application_name
173 : pub appname: Option<String>,
174 : pub feedback: ReplicationFeedback,
175 : }
176 :
177 0 : #[derive(Debug, Clone, Serialize, Deserialize)]
178 : pub struct WalReceiverState {
179 : /// None means it is recovery initiated by us (this safekeeper).
180 : pub conn_id: Option<ConnectionId>,
181 : pub status: WalReceiverStatus,
182 : }
183 :
184 : /// Walreceiver status. Currently only whether it passed voting stage and
185 : /// started receiving the stream, but it is easy to add more if needed.
186 0 : #[derive(Debug, Clone, Serialize, Deserialize)]
187 : pub enum WalReceiverStatus {
188 : Voting,
189 : Streaming,
190 : }
191 :
192 : /// Info about timeline on safekeeper ready for reporting.
193 0 : #[derive(Debug, Serialize, Deserialize)]
194 : pub struct TimelineStatus {
195 : pub tenant_id: TenantId,
196 : pub timeline_id: TimelineId,
197 : pub mconf: Configuration,
198 : pub acceptor_state: AcceptorStateStatus,
199 : pub pg_info: ServerInfo,
200 : pub flush_lsn: Lsn,
201 : pub timeline_start_lsn: Lsn,
202 : pub local_start_lsn: Lsn,
203 : pub commit_lsn: Lsn,
204 : pub backup_lsn: Lsn,
205 : pub peer_horizon_lsn: Lsn,
206 : pub remote_consistent_lsn: Lsn,
207 : pub peers: Vec<PeerInfo>,
208 : pub walsenders: Vec<WalSenderState>,
209 : pub walreceivers: Vec<WalReceiverState>,
210 : }
211 :
212 : /// Request to switch membership configuration.
213 0 : #[derive(Serialize, Deserialize)]
214 : #[serde(transparent)]
215 : pub struct TimelineMembershipSwitchRequest {
216 : pub mconf: Configuration,
217 : }
218 :
219 : /// In response both previous and current configuration are sent.
220 0 : #[derive(Serialize, Deserialize)]
221 : pub struct TimelineMembershipSwitchResponse {
222 : pub previous_conf: Configuration,
223 : pub current_conf: Configuration,
224 : }
225 :
226 0 : #[derive(Clone, Copy, Serialize, Deserialize)]
227 : pub struct TimelineDeleteResult {
228 : pub dir_existed: bool,
229 : }
230 :
231 : pub type TenantDeleteResult = std::collections::HashMap<String, TimelineDeleteResult>;
232 :
233 0 : fn lsn_invalid() -> Lsn {
234 0 : Lsn::INVALID
235 0 : }
236 :
237 : /// Data about safekeeper's timeline, mirrors broker.proto.
238 0 : #[derive(Debug, Clone, Deserialize, Serialize)]
239 : pub struct SkTimelineInfo {
240 : /// Term.
241 : pub term: Option<u64>,
242 : /// Term of the last entry.
243 : pub last_log_term: Option<u64>,
244 : /// LSN of the last record.
245 : #[serde(default = "lsn_invalid")]
246 : pub flush_lsn: Lsn,
247 : /// Up to which LSN safekeeper regards its WAL as committed.
248 : #[serde(default = "lsn_invalid")]
249 : pub commit_lsn: Lsn,
250 : /// LSN up to which safekeeper has backed WAL.
251 : #[serde(default = "lsn_invalid")]
252 : pub backup_lsn: Lsn,
253 : /// LSN of last checkpoint uploaded by pageserver.
254 : #[serde(default = "lsn_invalid")]
255 : pub remote_consistent_lsn: Lsn,
256 : #[serde(default = "lsn_invalid")]
257 : pub peer_horizon_lsn: Lsn,
258 : #[serde(default = "lsn_invalid")]
259 : pub local_start_lsn: Lsn,
260 : /// A connection string to use for WAL receiving.
261 : #[serde(default)]
262 : pub safekeeper_connstr: Option<String>,
263 : #[serde(default)]
264 : pub http_connstr: Option<String>,
265 : #[serde(default)]
266 : pub https_connstr: Option<String>,
267 : // Minimum of all active RO replicas flush LSN
268 : #[serde(default = "lsn_invalid")]
269 : pub standby_horizon: Lsn,
270 : }
271 :
272 0 : #[derive(Debug, Clone, Deserialize, Serialize)]
273 : pub struct TimelineCopyRequest {
274 : pub target_timeline_id: TimelineId,
275 : pub until_lsn: Lsn,
276 : }
277 :
278 0 : #[derive(Debug, Clone, Deserialize, Serialize)]
279 : pub struct TimelineTermBumpRequest {
280 : /// bump to
281 : pub term: Option<u64>,
282 : }
283 :
284 0 : #[derive(Debug, Clone, Deserialize, Serialize)]
285 : pub struct TimelineTermBumpResponse {
286 : // before the request
287 : pub previous_term: u64,
288 : pub current_term: u64,
289 : }
290 :
291 0 : #[derive(Debug, Clone, Deserialize, Serialize)]
292 : pub struct SafekeeperUtilization {
293 : pub timeline_count: u64,
294 : }
295 :
296 : /// pull_timeline request body.
297 0 : #[derive(Debug, Clone, Deserialize, Serialize)]
298 : pub struct PullTimelineRequest {
299 : pub tenant_id: TenantId,
300 : pub timeline_id: TimelineId,
301 : pub http_hosts: Vec<String>,
302 : }
303 :
304 0 : #[derive(Debug, Serialize, Deserialize)]
305 : pub struct PullTimelineResponse {
306 : // Donor safekeeper host
307 : pub safekeeper_host: String,
308 : // TODO: add more fields?
309 : }
|