mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-07 05:22:56 +00:00
1. Adds local-proxy to compute image and vm spec 2. Updates local-proxy config processing, writing PID to a file eagerly 3. Updates compute-ctl to understand local proxy compute spec and to send SIGHUP to local-proxy over that pid. closes https://github.com/neondatabase/cloud/issues/16867
57 lines
2.5 KiB
Rust
57 lines
2.5 KiB
Rust
//! Local Proxy is a feature of our BaaS Neon Authorize project.
|
|
//!
|
|
//! Local Proxy validates JWTs and manages the pg_session_jwt extension.
|
|
//! It also maintains a connection pool to postgres.
|
|
|
|
use anyhow::{Context, Result};
|
|
use camino::Utf8Path;
|
|
use compute_api::spec::LocalProxySpec;
|
|
use nix::sys::signal::Signal;
|
|
use utils::pid_file::{self, PidFileRead};
|
|
|
|
pub fn configure(local_proxy: &LocalProxySpec) -> Result<()> {
|
|
write_local_proxy_conf("/etc/local_proxy/config.json".as_ref(), local_proxy)?;
|
|
notify_local_proxy("/etc/local_proxy/pid".as_ref())?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Create or completely rewrite configuration file specified by `path`
|
|
fn write_local_proxy_conf(path: &Utf8Path, local_proxy: &LocalProxySpec) -> Result<()> {
|
|
let config =
|
|
serde_json::to_string_pretty(local_proxy).context("serializing LocalProxySpec to json")?;
|
|
std::fs::write(path, config).with_context(|| format!("writing {path}"))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Notify local proxy about a new config file.
|
|
fn notify_local_proxy(path: &Utf8Path) -> Result<()> {
|
|
match pid_file::read(path)? {
|
|
// if the file doesn't exist, or isn't locked, local_proxy isn't running
|
|
// and will naturally pick up our config later
|
|
PidFileRead::NotExist | PidFileRead::NotHeldByAnyProcess(_) => {}
|
|
PidFileRead::LockedByOtherProcess(pid) => {
|
|
// From the pid_file docs:
|
|
//
|
|
// > 1. The other process might exit at any time, turning the given PID stale.
|
|
// > 2. There is a small window in which `claim_for_current_process` has already
|
|
// > locked the file but not yet updates its contents. [`read`] will return
|
|
// > this variant here, but with the old file contents, i.e., a stale PID.
|
|
// >
|
|
// > The kernel is free to recycle PID once it has been `wait(2)`ed upon by
|
|
// > its creator. Thus, acting upon a stale PID, e.g., by issuing a `kill`
|
|
// > system call on it, bears the risk of killing an unrelated process.
|
|
// > This is an inherent limitation of using pidfiles.
|
|
// > The only race-free solution is to have a supervisor-process with a lifetime
|
|
// > that exceeds that of all of its child-processes (e.g., `runit`, `supervisord`).
|
|
//
|
|
// This is an ok risk as we only send a SIGHUP which likely won't actually
|
|
// kill the process, only reload config.
|
|
nix::sys::signal::kill(pid, Signal::SIGHUP).context("sending signal to local_proxy")?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|