Line data Source code
1 : use anyhow::{Ok, Result, anyhow};
2 : use tokio_postgres::NoTls;
3 : use tracing::{error, instrument, warn};
4 :
5 : use crate::compute::ComputeNode;
6 :
7 : /// Update timestamp in a row in a special service table to check
8 : /// that we can actually write some data in this particular timeline.
9 : #[instrument(skip_all)]
10 : pub async fn check_writability(compute: &ComputeNode) -> Result<()> {
11 : // Connect to the database.
12 : let conf = compute.get_tokio_conn_conf(Some("compute_ctl:availability_checker"));
13 : let (client, connection) = conf.connect(NoTls).await?;
14 : if client.is_closed() {
15 : return Err(anyhow!("connection to postgres closed"));
16 : }
17 :
18 : // The connection object performs the actual communication with the database,
19 : // so spawn it off to run on its own.
20 0 : tokio::spawn(async move {
21 0 : if let Err(e) = connection.await {
22 0 : error!("connection error: {}", e);
23 0 : }
24 0 : });
25 :
26 : let query = "
27 : INSERT INTO health_check VALUES (1, now())
28 : ON CONFLICT (id) DO UPDATE
29 : SET updated_at = now();";
30 :
31 : match client.simple_query(query).await {
32 : Result::Ok(result) => {
33 : if result.len() != 1 {
34 : return Err(anyhow::anyhow!(
35 : "expected 1 query results, but got {}",
36 : result.len()
37 : ));
38 : }
39 : }
40 : Err(err) => {
41 : if let Some(state) = err.code() {
42 : if state == &tokio_postgres::error::SqlState::DISK_FULL {
43 : warn!("Tenant disk is full");
44 : return Ok(());
45 : }
46 : }
47 : return Err(err.into());
48 : }
49 : }
50 :
51 : Ok(())
52 : }
|