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