LCOV - differential code coverage report
Current view: top level - control_plane/src - attachment_service.rs (source / functions) Coverage Total Hit UBC CBC
Current: f6946e90941b557c917ac98cd5a7e9506d180f3e.info Lines: 98.6 % 71 70 1 70
Current Date: 2023-10-19 02:04:12 Functions: 30.0 % 40 12 28 12
Baseline: c8637f37369098875162f194f92736355783b050.info
Baseline Date: 2023-10-18 20:25:20

           TLA  Line data    Source code
       1                 : use crate::{background_process, local_env::LocalEnv};
       2                 : use anyhow::anyhow;
       3                 : use camino::Utf8PathBuf;
       4                 : use serde::{Deserialize, Serialize};
       5                 : use serde_with::{serde_as, DisplayFromStr};
       6                 : use std::{path::PathBuf, process::Child};
       7                 : use utils::id::{NodeId, TenantId};
       8                 : 
       9                 : pub struct AttachmentService {
      10                 :     env: LocalEnv,
      11                 :     listen: String,
      12                 :     path: PathBuf,
      13                 : }
      14                 : 
      15                 : const COMMAND: &str = "attachment_service";
      16                 : 
      17                 : #[serde_as]
      18 CBC          12 : #[derive(Serialize, Deserialize)]
      19                 : pub struct AttachHookRequest {
      20                 :     #[serde_as(as = "DisplayFromStr")]
      21                 :     pub tenant_id: TenantId,
      22                 :     pub pageserver_id: Option<NodeId>,
      23                 : }
      24                 : 
      25              36 : #[derive(Serialize, Deserialize)]
      26                 : pub struct AttachHookResponse {
      27                 :     pub gen: Option<u32>,
      28                 : }
      29                 : 
      30                 : impl AttachmentService {
      31              38 :     pub fn from_env(env: &LocalEnv) -> Self {
      32              38 :         let path = env.base_data_dir.join("attachments.json");
      33              38 : 
      34              38 :         // Makes no sense to construct this if pageservers aren't going to use it: assume
      35              38 :         // pageservers have control plane API set
      36              38 :         let listen_url = env.control_plane_api.clone().unwrap();
      37              38 : 
      38              38 :         let listen = format!(
      39              38 :             "{}:{}",
      40              38 :             listen_url.host_str().unwrap(),
      41              38 :             listen_url.port().unwrap()
      42              38 :         );
      43              38 : 
      44              38 :         Self {
      45              38 :             env: env.clone(),
      46              38 :             path,
      47              38 :             listen,
      48              38 :         }
      49              38 :     }
      50                 : 
      51              26 :     fn pid_file(&self) -> Utf8PathBuf {
      52              26 :         Utf8PathBuf::from_path_buf(self.env.base_data_dir.join("attachment_service.pid"))
      53              26 :             .expect("non-Unicode path")
      54              26 :     }
      55                 : 
      56              13 :     pub fn start(&self) -> anyhow::Result<Child> {
      57              13 :         let path_str = self.path.to_string_lossy();
      58              13 : 
      59              13 :         background_process::start_process(
      60              13 :             COMMAND,
      61              13 :             &self.env.base_data_dir,
      62              13 :             &self.env.attachment_service_bin(),
      63              13 :             ["-l", &self.listen, "-p", &path_str],
      64              13 :             [],
      65              13 :             background_process::InitialPidFile::Create(&self.pid_file()),
      66              13 :             // TODO: a real status check
      67              13 :             || Ok(true),
      68              13 :         )
      69              13 :     }
      70                 : 
      71              13 :     pub fn stop(&self, immediate: bool) -> anyhow::Result<()> {
      72              13 :         background_process::stop_process(immediate, COMMAND, &self.pid_file())
      73              13 :     }
      74                 : 
      75                 :     /// Call into the attach_hook API, for use before handing out attachments to pageservers
      76              12 :     pub fn attach_hook(
      77              12 :         &self,
      78              12 :         tenant_id: TenantId,
      79              12 :         pageserver_id: NodeId,
      80              12 :     ) -> anyhow::Result<Option<u32>> {
      81              12 :         use hyper::StatusCode;
      82              12 : 
      83              12 :         let url = self
      84              12 :             .env
      85              12 :             .control_plane_api
      86              12 :             .clone()
      87              12 :             .unwrap()
      88              12 :             .join("attach_hook")
      89              12 :             .unwrap();
      90              12 :         let client = reqwest::blocking::ClientBuilder::new()
      91              12 :             .build()
      92              12 :             .expect("Failed to construct http client");
      93              12 : 
      94              12 :         let request = AttachHookRequest {
      95              12 :             tenant_id,
      96              12 :             pageserver_id: Some(pageserver_id),
      97              12 :         };
      98                 : 
      99              12 :         let response = client.post(url).json(&request).send()?;
     100              12 :         if response.status() != StatusCode::OK {
     101 UBC           0 :             return Err(anyhow!("Unexpected status {}", response.status()));
     102 CBC          12 :         }
     103                 : 
     104              12 :         let response = response.json::<AttachHookResponse>()?;
     105              12 :         Ok(response.gen)
     106              12 :     }
     107                 : }
        

Generated by: LCOV version 2.1-beta