mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 14:58:03 +03:00
edenapi: add option to call files2 endpoint instead
Summary: Now that we have a files2 endpoint that can return errors, let's add an option to call it from the client. Reviewed By: quark-zju Differential Revision: D33283030 fbshipit-source-id: 3eda0fe870be1f4b74e0f0f60b11518c7bfe508f
This commit is contained in:
parent
c43e88e2c8
commit
e1307b12fc
@ -54,3 +54,17 @@ Check files in response.
|
||||
"sha256": bin("a1fff0ffefb9eace7230c24e50731f0a91c62f9cefdfe77121c2f607125dffae"),
|
||||
"content_id": bin("888dcf533a354c23e4bf67e1ada984d96bb1089b0c3c03f4c2cb773709e7aa42"),
|
||||
"total_size": 13}}}}]
|
||||
|
||||
$ hgedenapi debugapi -e filesattrs -f req --config edenapi.use-files2=True
|
||||
[{"key": {"node": bin("17b8d4e3bafd4ec4812ad7c930aace9bf07ab033"),
|
||||
"path": "copy.txt"},
|
||||
"result": {"Ok": {"key": {"node": bin("17b8d4e3bafd4ec4812ad7c930aace9bf07ab033"),
|
||||
"path": "copy.txt"},
|
||||
"content": {"metadata": {"size": None,
|
||||
"flags": None},
|
||||
"hg_file_blob": b"\x01\ncopy: test.txt\ncopyrev: 186cafa3319c24956783383dc44c5cbc68c5a0ca\n\x01\ntest content\n"},
|
||||
"parents": None,
|
||||
"aux_data": {"sha1": bin("4fe2b8dd12cd9cd6a413ea960cd8c09c25f19527"),
|
||||
"sha256": bin("a1fff0ffefb9eace7230c24e50731f0a91c62f9cefdfe77121c2f607125dffae"),
|
||||
"content_id": bin("888dcf533a354c23e4bf67e1ada984d96bb1089b0c3c03f4c2cb773709e7aa42"),
|
||||
"total_size": 13}}}}]
|
||||
|
@ -140,8 +140,8 @@ pub struct HttpClientBuilder {
|
||||
encoding: Option<Encoding>,
|
||||
min_transfer_speed: Option<MinTransferSpeed>,
|
||||
max_retry_per_request: usize,
|
||||
|
||||
http_config: http_client::Config,
|
||||
use_files2: bool,
|
||||
}
|
||||
|
||||
impl HttpClientBuilder {
|
||||
@ -234,6 +234,7 @@ impl HttpClientBuilder {
|
||||
);
|
||||
let max_retry_per_request =
|
||||
get_config::<usize>(config, "edenapi", "max-retry-per-request")?.unwrap_or(10);
|
||||
let use_files2 = get_config::<bool>(config, "edenapi", "use-files2")?.unwrap_or_default();
|
||||
|
||||
let mut http_config = hg_http::http_config(config);
|
||||
http_config.verbose_stats |= debug;
|
||||
@ -261,6 +262,7 @@ impl HttpClientBuilder {
|
||||
min_transfer_speed,
|
||||
max_retry_per_request,
|
||||
http_config,
|
||||
use_files2,
|
||||
})
|
||||
}
|
||||
|
||||
@ -346,7 +348,6 @@ impl HttpClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
/// Maximum number of locations per location to has request. Larger requests will be split up
|
||||
/// into concurrently-sent batches.
|
||||
pub fn max_location_to_hash(mut self, size: Option<usize>) -> Self {
|
||||
@ -354,7 +355,6 @@ impl HttpClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
/// Timeout for HTTP requests sent by the client.
|
||||
pub fn timeout(mut self, timeout: Duration) -> Self {
|
||||
self.timeout = Some(timeout);
|
||||
@ -446,6 +446,7 @@ pub(crate) struct Config {
|
||||
pub(crate) min_transfer_speed: Option<MinTransferSpeed>,
|
||||
pub(crate) max_retry_per_request: usize,
|
||||
pub(crate) http_config: http_client::Config,
|
||||
pub(crate) use_files2: bool,
|
||||
}
|
||||
|
||||
impl TryFrom<HttpClientBuilder> for Config {
|
||||
@ -474,6 +475,7 @@ impl TryFrom<HttpClientBuilder> for Config {
|
||||
min_transfer_speed,
|
||||
max_retry_per_request,
|
||||
http_config,
|
||||
use_files2,
|
||||
} = builder;
|
||||
|
||||
// Check for missing required fields.
|
||||
@ -514,6 +516,7 @@ impl TryFrom<HttpClientBuilder> for Config {
|
||||
min_transfer_speed,
|
||||
max_retry_per_request,
|
||||
http_config,
|
||||
use_files2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ static FILES_ATTRS_INFLIGHT: Counter = Counter::new("edenapi.files_attrs_infligh
|
||||
mod paths {
|
||||
pub const HEALTH_CHECK: &str = "health_check";
|
||||
pub const FILES: &str = "files";
|
||||
pub const FILES2: &str = "files2";
|
||||
pub const HISTORY: &str = "history";
|
||||
pub const TREES: &str = "trees";
|
||||
pub const COMMIT_REVLOG_DATA: &str = "commit/revlog_data";
|
||||
@ -422,26 +423,37 @@ impl Client {
|
||||
|
||||
let guards = vec![FILES_INFLIGHT.entrance_guard(keys.len())];
|
||||
|
||||
let url = self.build_url(paths::FILES)?;
|
||||
let use_files2 = self.config().use_files2;
|
||||
let path = if use_files2 {
|
||||
paths::FILES2
|
||||
} else {
|
||||
paths::FILES
|
||||
};
|
||||
|
||||
let url = self.build_url(path)?;
|
||||
let requests = self.prepare_requests(&url, keys, self.config().max_files, |keys| {
|
||||
let req = FileRequest { keys, reqs: vec![] };
|
||||
self.log_request(&req, "files");
|
||||
req
|
||||
})?;
|
||||
|
||||
// Convert files v1's FileEntry response into a files v2 FileResponse.
|
||||
let response = self.fetch_guard::<FileEntry>(requests, guards)?;
|
||||
let entries = response
|
||||
.entries
|
||||
.map_ok(|file_entry| FileResponse {
|
||||
key: file_entry.key.clone(),
|
||||
result: Ok(file_entry),
|
||||
if use_files2 {
|
||||
Ok(self.fetch_guard::<FileResponse>(requests, guards)?)
|
||||
} else {
|
||||
// Convert files v1's FileEntry response into a files v2 FileResponse.
|
||||
let response = self.fetch_guard::<FileEntry>(requests, guards)?;
|
||||
let entries = response
|
||||
.entries
|
||||
.map_ok(|file_entry| FileResponse {
|
||||
key: file_entry.key.clone(),
|
||||
result: Ok(file_entry),
|
||||
})
|
||||
.boxed();
|
||||
Ok(Response {
|
||||
entries,
|
||||
stats: response.stats,
|
||||
})
|
||||
.boxed();
|
||||
Ok(Response {
|
||||
entries,
|
||||
stats: response.stats,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn fetch_trees(
|
||||
@ -480,26 +492,37 @@ impl Client {
|
||||
|
||||
let guards = vec![FILES_ATTRS_INFLIGHT.entrance_guard(reqs.len())];
|
||||
|
||||
let url = self.build_url(paths::FILES)?;
|
||||
let use_files2 = self.config().use_files2;
|
||||
let path = if use_files2 {
|
||||
paths::FILES2
|
||||
} else {
|
||||
paths::FILES
|
||||
};
|
||||
|
||||
let url = self.build_url(path)?;
|
||||
let requests = self.prepare_requests(&url, reqs, self.config().max_files, |reqs| {
|
||||
let req = FileRequest { reqs, keys: vec![] };
|
||||
self.log_request(&req, "files");
|
||||
req
|
||||
})?;
|
||||
|
||||
// Convert files v1's FileEntry response into a files v2 FileResponse.
|
||||
let response = self.fetch_guard::<FileEntry>(requests, guards)?;
|
||||
let entries = response
|
||||
.entries
|
||||
.map_ok(|file_entry| FileResponse {
|
||||
key: file_entry.key.clone(),
|
||||
result: Ok(file_entry),
|
||||
if use_files2 {
|
||||
Ok(self.fetch_guard::<FileResponse>(requests, guards)?)
|
||||
} else {
|
||||
// Convert files v1's FileEntry response into a files v2 FileResponse.
|
||||
let response = self.fetch_guard::<FileEntry>(requests, guards)?;
|
||||
let entries = response
|
||||
.entries
|
||||
.map_ok(|file_entry| FileResponse {
|
||||
key: file_entry.key.clone(),
|
||||
result: Ok(file_entry),
|
||||
})
|
||||
.boxed();
|
||||
Ok(Response {
|
||||
entries,
|
||||
stats: response.stats,
|
||||
})
|
||||
.boxed();
|
||||
Ok(Response {
|
||||
entries,
|
||||
stats: response.stats,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Upload a single file
|
||||
|
Loading…
Reference in New Issue
Block a user