1use std::fmt::Debug;
2use std::sync::Arc;
3use std::sync::LazyLock;
4
5use async_trait::async_trait;
6use futures::sink::{Sink, SinkExt};
7
8use super::{ClientInfo, DefaultServerParameterProvider, StartupHandler};
9use crate::api::{
10 ConnectionManager, PgWireConnectionState, PidSecretKeyGenerator, RandomPidSecretKeyGenerator,
11};
12use crate::error::{PgWireError, PgWireResult};
13use crate::messages::response::{ReadyForQuery, TransactionStatus};
14use crate::messages::{PgWireBackendMessage, PgWireFrontendMessage};
15
16static DEFAULT_PID_GENERATOR: LazyLock<RandomPidSecretKeyGenerator> =
17 LazyLock::new(RandomPidSecretKeyGenerator::default);
18
19#[async_trait]
20pub trait NoopStartupHandler: StartupHandler {
22 fn connection_manager(&self) -> Option<Arc<ConnectionManager>> {
23 None
24 }
25
26 fn pid_secret_key_generator(&self) -> &dyn PidSecretKeyGenerator {
27 &*DEFAULT_PID_GENERATOR
28 }
29
30 async fn post_startup<C>(
31 &self,
32 _client: &mut C,
33 _message: PgWireFrontendMessage,
34 ) -> PgWireResult<()>
35 where
36 C: ClientInfo + Sink<PgWireBackendMessage> + Unpin + Send,
37 C::Error: Debug,
38 PgWireError: From<<C as Sink<PgWireBackendMessage>>::Error>,
39 {
40 Ok(())
41 }
42}
43
44#[async_trait]
45impl<H> StartupHandler for H
46where
47 H: NoopStartupHandler,
48{
49 async fn on_startup<C>(
50 &self,
51 client: &mut C,
52 message: PgWireFrontendMessage,
53 ) -> PgWireResult<()>
54 where
55 C: ClientInfo + Sink<PgWireBackendMessage> + Unpin + Send,
56 C::Error: Debug,
57 PgWireError: From<<C as Sink<PgWireBackendMessage>>::Error>,
58 {
59 if let PgWireFrontendMessage::Startup(ref startup) = message {
60 super::protocol_negotiation(client, startup).await?;
61 super::save_startup_parameters_to_metadata(client, startup);
62 let (pid, secret_key) = self.pid_secret_key_generator().generate(client);
63 client.set_pid_and_secret_key(pid, secret_key);
64 if let Some(manager) = self.connection_manager() {
65 super::register_connection(client, &manager);
66 }
67 super::finish_authentication0(client, &DefaultServerParameterProvider::default())
68 .await?;
69
70 self.post_startup(client, message).await?;
71
72 client
73 .send(PgWireBackendMessage::ReadyForQuery(ReadyForQuery::new(
74 TransactionStatus::Idle,
75 )))
76 .await?;
77 client.set_state(PgWireConnectionState::ReadyForQuery);
78 }
79
80 Ok(())
81 }
82}
83
84impl NoopStartupHandler for crate::api::NoopHandler {}