Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions crates/bin/docs_rs_web/src/handlers/build_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ pub(crate) async fn build_details_handler(
.await?
.ok_or(AxumNope::BuildNotFound)?;

let metadata = MetaData::from_crate(
&mut conn,
params.name(),
&version,
Some(params.req_version().clone()),
)
.await?;
let params = params.apply_metadata(&metadata);

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

let (output, all_log_filenames, current_filename) = if let Some(output) = row.output {
// legacy case, for old builds the build log was stored in the database.
(output, Vec::new(), None)
Expand Down Expand Up @@ -155,15 +168,6 @@ pub(crate) async fn build_details_handler(
(file_content, all_log_filenames, current_filename)
};

let metadata = MetaData::from_crate(
&mut conn,
params.name(),
&version,
Some(params.req_version().clone()),
)
.await?;
let params = params.apply_metadata(&metadata);

Ok(BuildDetailsPage {
metadata,
build_details: BuildDetails {
Expand Down
10 changes: 7 additions & 3 deletions crates/bin/docs_rs_web/src/handlers/crate_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,14 +469,18 @@ pub(crate) async fn crate_details_handler(

let mut details = CrateDetails::from_matched_release(&mut conn, matched_release).await?;

let build_statistics =
BuildStatistics::fetch_for_release(&mut conn, details.crate_id, details.release_id).await?;

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

match details.fetch_readme(&storage).await {
Ok(readme) => details.readme = readme.or(details.readme),
Err(e) => warn!(?e, "error fetching readme"),
}

let build_statistics =
BuildStatistics::fetch_for_release(&mut conn, details.crate_id, details.release_id).await?;

let CrateDetails {
version,
name,
Expand Down
31 changes: 28 additions & 3 deletions crates/bin/docs_rs_web/src/handlers/rustdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use axum_extra::{
typed_header::TypedHeader,
};
use docs_rs_cargo_metadata::Dependency;
use docs_rs_database::Pool;
use docs_rs_headers::{ETagComputer, IfNoneMatch, X_ROBOTS_TAG};
use docs_rs_registry_api::OwnerKind;
use docs_rs_rustdoc_json::RustdocJsonFormatVersion;
Expand Down Expand Up @@ -186,13 +187,13 @@ pub(crate) struct RustdocRedirectorParams {
/// Handler called for `/:crate` and `/:crate/:version` URLs. Automatically redirects to the docs
/// or crate details page based on whether the given crate version was successfully built.
#[allow(clippy::too_many_arguments)]
#[instrument(skip(storage, conn))]
#[instrument(skip(storage, pool))]
pub(crate) async fn rustdoc_redirector_handler(
Path(params): Path<RustdocRedirectorParams>,
original_uri: Uri,
matched_path: MatchedPath,
Extension(storage): Extension<Arc<AsyncStorage>>,
mut conn: DbConnection,
Extension(pool): Extension<Pool>,
if_none_match: Option<TypedHeader<IfNoneMatch>>,
RawQuery(original_query): RawQuery,
) -> AxumResult<impl IntoResponse> {
Expand Down Expand Up @@ -291,6 +292,9 @@ pub(crate) async fn rustdoc_redirector_handler(
.map_err(AxumNope::BadRequest)?
.with_page_kind(PageKind::Rustdoc);

// NOTE: we try to shorten the time we hold the database connection from the pool.
let mut conn = pool.get_async().await?;

// it doesn't matter if the version that was given was exact or not, since we're redirecting
// anyway
let matched_release = match_version(&mut conn, &crate_name, &params.req_version().clone())
Expand All @@ -316,6 +320,10 @@ pub(crate) async fn rustdoc_redirector_handler(
return async {
let krate = CrateDetails::from_matched_release(&mut conn, matched_release).await?;

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

match storage
.stream_rustdoc_file(
params.name(),
Expand Down Expand Up @@ -597,6 +605,10 @@ pub(crate) async fn rustdoc_html_server_handler(

let krate = CrateDetails::from_matched_release(&mut conn, matched_release).await?;

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

trace!(
?params,
doc_targets=?krate.metadata.doc_targets,
Expand Down Expand Up @@ -784,9 +796,13 @@ pub(crate) async fn target_redirect_handler(
.await?
.into_canonical_req_version_or_else(|_, _| AxumNope::VersionNotFound)?;
let params = params.apply_matched_release(&matched_release);
trace!(?params, "parsed params");

let crate_details = CrateDetails::from_matched_release(&mut conn, matched_release).await?;
trace!(?params, "parsed params");

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

let storage_path = params.storage_path();
trace!(storage_path, "checking if path exists in other version");
Expand Down Expand Up @@ -893,6 +909,10 @@ pub(crate) async fn json_download_handler(

let krate = CrateDetails::from_matched_release(&mut conn, matched_release).await?;

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

let wanted_format_version = if let Some(request_format_version) = json_params.format_version {
// axum doesn't support extension suffixes in the route yet, not as parameter, and not
// statically, when combined with a parameter (like `.../{format_version}.gz`).
Expand Down Expand Up @@ -1001,6 +1021,11 @@ pub(crate) async fn download_handler(
CachePolicy::ForeverInCdn(confirmed_name.into()),
)
})?;

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

params = params.apply_matched_release(&matched_release);

let version = &matched_release.release.version;
Expand Down
42 changes: 23 additions & 19 deletions crates/bin/docs_rs_web/src/handlers/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,29 @@ pub(crate) async fn source_browser_handler(

let inner_path = params.inner_path();

let current_folder = if let Some(last_slash_pos) = inner_path.rfind('/') {
&inner_path[..last_slash_pos + 1]
} else {
""
};
let show_parent_link = !current_folder.is_empty();

let file_list = FileList::from_path(&mut conn, params.name(), version, current_folder)
.await?
.unwrap_or_default();

let metadata = MetaData::from_crate(
&mut conn,
params.name(),
version,
Some(params.req_version().clone()),
)
.await?;

// NOTE: we want to give back the db connection to the pool
// before we do the long S3 requests.
drop(conn);

// try to get actual file first
// skip if request is a directory
let stream = if !params.path_is_folder() {
Expand Down Expand Up @@ -326,25 +349,6 @@ pub(crate) async fn source_browser_handler(
(None, None)
};

let current_folder = if let Some(last_slash_pos) = inner_path.rfind('/') {
&inner_path[..last_slash_pos + 1]
} else {
""
};
let show_parent_link = !current_folder.is_empty();

let file_list = FileList::from_path(&mut conn, params.name(), version, current_folder)
.await?
.unwrap_or_default();

let metadata = MetaData::from_crate(
&mut conn,
params.name(),
version,
Some(params.req_version().clone()),
)
.await?;

Ok(SourcePage {
file_list,
metadata,
Expand Down
28 changes: 17 additions & 11 deletions crates/lib/docs_rs_database/src/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,38 @@ impl Pool {
let max_lifetime = Duration::from_secs(30 * 60);
let idle_timeout = Duration::from_secs(10 * 60);

let async_pool = PgPoolOptions::new()
let mut options = PgPoolOptions::new()
.max_connections(config.max_pool_size)
.min_connections(config.min_pool_idle)
.max_lifetime(max_lifetime)
.acquire_timeout(acquire_timeout)
.idle_timeout(idle_timeout)
.after_connect({
.idle_timeout(idle_timeout);

if cfg!(test) {
options = options.test_before_acquire(false);
}

if schema != DEFAULT_SCHEMA {
options = options.after_connect({
let schema = schema.to_owned();
move |conn, _meta| {
Box::pin({
let schema = schema.clone();

async move {
if schema != DEFAULT_SCHEMA {
conn.execute(
format!("SET search_path TO {schema}, {DEFAULT_SCHEMA};")
.as_str(),
)
.await?;
}
conn.execute(
format!("SET search_path TO {schema}, {DEFAULT_SCHEMA};").as_str(),
)
.await?;

Ok(())
}
})
}
})
});
}

let async_pool = options
.connect_lazy(&config.database_url)
.map_err(PoolError::AsyncPoolCreationFailed)?;

Expand Down
Loading