Skip to content

Commit

Permalink
Replace the health check with a readiness check.
Browse files Browse the repository at this point in the history
The NDC specification states that the health check should respond with
`200 OK` when the connector is ready to start accepting requests (i.e.
"readiness").

Whether the underlying data source is up and running is not important
here.

This adds a default implementation to the method to make it trivial for
connector authors to handle this particular request. The method name has
been changed to clarify matters and also to force connector authors to
understand the change.

We will consider adding further endpoints to check "liveness" and
"connectedness" in the future.
  • Loading branch information
SamirTalwar committed Aug 8, 2024
1 parent efed395 commit 10fdfb7
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 18 deletions.
15 changes: 11 additions & 4 deletions crates/sdk/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub use error::*;
/// a connection string would be configuration, but a connection pool object
/// created from that connection string would be state.
#[async_trait]
pub trait Connector {
pub trait Connector: Send {
/// The type of validated configuration
type Configuration: Sync + Send;
/// The type of unserializable state
Expand All @@ -55,9 +55,16 @@ pub trait Connector {

/// Check the health of the connector.
///
/// For example, this function should check that the connector
/// is able to reach its data source over the network.
async fn health_check(configuration: &Self::Configuration, state: &Self::State) -> Result<()>;
/// This should simply verify that the connector is ready to start accepting
/// requests. It should not verify that external data sources are available.
///
/// For most use cases, the default implementation should be fine.
async fn get_health_readiness(
_configuration: &Self::Configuration,
_state: &Self::State,
) -> Result<()> {
Ok(())
}

/// Get the connector's capabilities.
///
Expand Down
7 changes: 0 additions & 7 deletions crates/sdk/src/connector/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,6 @@ impl Connector for Example {
Ok(())
}

async fn health_check(
_configuration: &Self::Configuration,
_state: &Self::State,
) -> Result<()> {
Ok(())
}

async fn get_capabilities() -> models::Capabilities {
models::Capabilities {
relationships: None,
Expand Down
17 changes: 10 additions & 7 deletions crates/sdk/src/default_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use axum::{
http::{HeaderValue, Request, StatusCode},
response::IntoResponse as _,
routing::{get, post},
Json, Router,
Json,
};
use axum_extra::extract::WithRejection;
use clap::{Parser, Subcommand};
Expand Down Expand Up @@ -293,25 +293,28 @@ pub async fn init_server_state<Setup: ConnectorSetup>(
Ok(ServerState::new(configuration, state, metrics))
}

pub fn create_router<C>(state: ServerState<C>, service_token_secret: Option<String>) -> Router
pub fn create_router<C>(
state: ServerState<C>,
service_token_secret: Option<String>,
) -> axum::Router<()>
where
C: Connector + 'static,
C::Configuration: Clone,
C::State: Clone,
{
Router::new()
axum::Router::new()
.route("/capabilities", get(get_capabilities::<C>))
.route("/health", get(get_health::<C>))
.route("/metrics", get(get_metrics::<C>))
.route("/schema", get(get_schema::<C>))
.route("/query", post(post_query::<C>))
.route("/query/explain", post(post_query_explain::<C>))
.route("/mutation", post(post_mutation::<C>))
.route("/mutation/explain", post(post_mutation_explain::<C>))
.with_state(state)
.layer(ValidateRequestHeaderLayer::custom(auth_handler(
service_token_secret,
)))
.route("/health", get(get_health_readiness::<C>)) // health checks are not authenticated
.with_state(state)
.layer(
TraceLayer::new_for_http()
.make_span_with(make_span)
Expand Down Expand Up @@ -382,8 +385,8 @@ async fn get_capabilities<C: Connector>() -> JsonResponse<CapabilitiesResponse>
.into()
}

async fn get_health<C: Connector>(State(state): State<ServerState<C>>) -> Result<()> {
C::health_check(&state.configuration, &state.state).await
async fn get_health_readiness<C: Connector>(State(state): State<ServerState<C>>) -> Result<()> {
C::get_health_readiness(&state.configuration, &state.state).await
}

async fn get_schema<C: Connector>(
Expand Down

0 comments on commit 10fdfb7

Please sign in to comment.