introduce EdenApiContext object

Summary:
I want to enable EdenApiHandlers to fetch other repo objects, but that requires various other objects not currently available. I don't want to complicate the handler signature with multiple additional args, so introduce a context object that can contain the dependent objects (i.e. RequestContext and ServerContext).

I tucked the path and query extractors into the context since they are barely used by any handlers (in fact, the path extractor is not used at all).

Reviewed By: markbt

Differential Revision: D45019176

fbshipit-source-id: ec4427d2f134277e89a8c48018f29c5f56cdc60d
This commit is contained in:
Muir Manders 2023-04-26 16:51:14 -07:00 committed by Facebook GitHub Bot
parent 4556b1d1f9
commit d1f0dab4de
10 changed files with 84 additions and 73 deletions

View File

@ -27,6 +27,7 @@ use mononoke_api::CompatBlame;
use mononoke_api_hg::HgRepoContext;
use mononoke_types::blame_v2::BlameV2;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerResult;
@ -53,11 +54,10 @@ impl EdenApiHandler for BlameHandler {
}
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let blames = request
.files
.into_iter()

View File

@ -23,6 +23,7 @@ use mercurial_types::HgChangesetId;
use mercurial_types::HgNodeHash;
use mononoke_api_hg::HgRepoContext;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerResult;
@ -44,11 +45,10 @@ impl EdenApiHandler for BookmarksHandler {
const ENDPOINT: &'static str = "/bookmarks";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let fetches = request
.bookmarks
.into_iter()
@ -83,13 +83,11 @@ impl EdenApiHandler for SetBookmarkHandler {
const ENDPOINT: &'static str = "/bookmarks/set";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
Ok(stream::once(set_bookmark(
repo,
ectx.repo(),
request.bookmark,
request.to,
request.from,

View File

@ -72,6 +72,7 @@ use tunables::tunables;
use types::HgId;
use types::Parents;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerInfo;
@ -143,11 +144,10 @@ impl EdenApiHandler for LocationToHashHandler {
}
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let hgid_list = request
.requests
.into_iter()
@ -274,11 +274,10 @@ impl EdenApiHandler for HashLookupHandler {
const ENDPOINT: &'static str = "/commit/hash_lookup";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
use CommitHashLookupRequest::*;
Ok(stream::iter(request.batch.into_iter())
.then(move |request| {
@ -311,11 +310,10 @@ impl EdenApiHandler for UploadHgChangesetsHandler {
const ENDPOINT: &'static str = "/upload/changesets";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let changesets = request.changesets;
let mutations = request.mutations;
let changesets_data = changesets
@ -365,11 +363,11 @@ impl EdenApiHandler for UploadBonsaiChangesetHandler {
const ENDPOINT: &'static str = "/upload/changeset/bonsai";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let query = ectx.query();
let bubble_id = query.bubble_id.map(BubbleId::new);
let cs = request.changeset;
let repo = &repo;
@ -438,12 +436,10 @@ impl EdenApiHandler for FetchSnapshotHandler {
const ENDPOINT: &'static str = "/snapshot";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = &repo;
let repo = ectx.repo();
let cs_id = ChangesetId::from(request.cs_id);
let bubble_id = repo
.ephemeral_store()
@ -526,12 +522,10 @@ impl EdenApiHandler for AlterSnapshotHandler {
const ENDPOINT: &'static str = "/snapshot/alter";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = &repo;
let repo = ectx.repo();
let cs_id = ChangesetId::from(request.cs_id);
let id = repo
.ephemeral_store()
@ -578,11 +572,10 @@ impl EdenApiHandler for EphemeralPrepareHandler {
const ENDPOINT: &'static str = "/ephemeral/prepare";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
Ok(stream::once(async move {
Ok(EphemeralPrepareResponse {
bubble_id: repo
@ -611,11 +604,10 @@ impl EdenApiHandler for GraphHandlerV2 {
const ENDPOINT: &'static str = "/commit/graph_v2";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let heads = request
.heads
.into_iter()
@ -657,11 +649,10 @@ impl EdenApiHandler for CommitMutationsHandler {
const ENDPOINT: &'static str = "/commit/mutations";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
if !tunables().mutation_generate_for_draft().unwrap_or_default() {
return Ok(stream::empty().boxed());
}
@ -697,11 +688,11 @@ impl EdenApiHandler for CommitTranslateId {
const ENDPOINT: &'static str = "/commit/translate_id";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let mut hg_ids = Vec::new();
let mut bonsai_ids = Vec::new();
let mut git_ids = Vec::new();

View File

@ -52,6 +52,7 @@ use rate_limiting::Metric;
use serde::Deserialize;
use types::Key;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerInfo;
@ -102,11 +103,10 @@ impl EdenApiHandler for FilesHandler {
}
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let ctx = repo.ctx().clone();
let len = request.keys.len() + request.reqs.len();
@ -151,11 +151,10 @@ impl EdenApiHandler for Files2Handler {
}
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let ctx = repo.ctx().clone();
let len = request.keys.len() + request.reqs.len();
@ -387,11 +386,10 @@ impl EdenApiHandler for UploadHgFilenodesHandler {
const ENDPOINT: &'static str = "/upload/filenodes";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let tokens = request
.batch
.into_iter()
@ -415,11 +413,10 @@ impl EdenApiHandler for DownloadFileHandler {
const ENDPOINT: &'static str = "/download/file";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let content = repo
.download_file(request)
.await?

View File

@ -53,6 +53,30 @@ where
pub type HandlerResult<'a, Response> =
Result<BoxStream<'a, anyhow::Result<Response>>, HandlerError>;
pub struct EdenApiContext<P, Q> {
repo: HgRepoContext,
path: P,
query: Q,
}
impl<P, Q> EdenApiContext<P, Q> {
pub fn new(repo: HgRepoContext, path: P, query: Q) -> Self {
Self { repo, path, query }
}
pub fn repo(&self) -> HgRepoContext {
self.repo.clone()
}
#[allow(unused)]
pub fn path(&self) -> &P {
&self.path
}
pub fn query(&self) -> &Q {
&self.query
}
}
#[async_trait]
pub trait EdenApiHandler: 'static {
type PathExtractor: PathExtractorWithRepo = BasicPathExtractor;
@ -72,9 +96,7 @@ pub trait EdenApiHandler: 'static {
}
async fn handler(
repo: HgRepoContext,
path: Self::PathExtractor,
query: Self::QueryStringExtractor,
ctx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response>;
}

View File

@ -21,6 +21,7 @@ use mercurial_types::HgNodeHash;
use mononoke_api_hg::HgRepoContext;
use types::Key;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerResult;
@ -44,11 +45,10 @@ impl EdenApiHandler for HistoryHandler {
const ENDPOINT: &'static str = "/history";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let HistoryRequest { keys, length } = request;
let fetches = keys.into_iter().map(move |key| {

View File

@ -22,6 +22,7 @@ use mercurial_types::HgChangesetId;
use mercurial_types::HgNodeHash;
use mononoke_api_hg::HgRepoContext;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerResult;
@ -40,13 +41,11 @@ impl EdenApiHandler for LandStackHandler {
const ENDPOINT: &'static str = "/land";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
Ok(stream::once(land_stack(
repo,
ectx.repo(),
request.bookmark,
request.head,
request.base,

View File

@ -32,6 +32,7 @@ use mononoke_api_hg::HgRepoContext;
use repo_blobstore::RepoBlobstoreRef;
use repo_identity::RepoIdentityRef;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerResult;
@ -211,11 +212,10 @@ impl EdenApiHandler for LookupHandler {
const ENDPOINT: &'static str = "/lookup";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let tokens = request
.batch
.into_iter()

View File

@ -81,6 +81,8 @@ pub(crate) use handler::HandlerError;
pub(crate) use handler::HandlerResult;
pub(crate) use handler::PathExtractorWithRepo;
use self::handler::EdenApiContext;
/// Enum identifying the EdenAPI method that each handler corresponds to.
/// Used to identify the handler for logging and stats collection.
#[derive(Copy, Clone)]
@ -271,7 +273,7 @@ where
{
let (future_stats, res) = async {
let path = Handler::PathExtractor::take_from(&mut state);
let query_string = Handler::QueryStringExtractor::take_from(&mut state);
let query = Handler::QueryStringExtractor::take_from(&mut state);
let content_encoding = ContentEncoding::from_state(&state);
state.put(HandlerInfo::new(path.repo(), Handler::API_METHOD));
@ -289,9 +291,11 @@ where
if let Some(rd) = RequestDumper::try_borrow_mut_from(&mut state) {
rd.add_request(&request);
};
}
match Handler::handler(repo, path, query_string, request).await {
let ectx = EdenApiContext::new(repo, path, query);
match Handler::handler(ectx, request).await {
Ok(responses) => Ok(encode_response_stream(
monitor_request(&state, responses),
content_encoding,

View File

@ -50,6 +50,7 @@ use tunables::tunables;
use types::Key;
use types::RepoPathBuf;
use super::handler::EdenApiContext;
use super::EdenApiHandler;
use super::EdenApiMethod;
use super::HandlerInfo;
@ -247,11 +248,10 @@ impl EdenApiHandler for UploadTreesHandler {
const ENDPOINT: &'static str = "/upload/trees";
async fn handler(
repo: HgRepoContext,
_path: Self::PathExtractor,
_query: Self::QueryStringExtractor,
ectx: EdenApiContext<Self::PathExtractor, Self::QueryStringExtractor>,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
let repo = ectx.repo();
let tokens = request
.batch
.into_iter()