mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-07 20:46:11 +00:00
fix(odm): resolve pagination Clippy failures
This commit is contained in:
@@ -283,19 +283,19 @@ pub struct FetchRequest {
|
|||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
|
||||||
pub enum ListPageError {
|
pub enum ListPageError {
|
||||||
#[error("truncated listing has no continuation token")]
|
#[error("truncated listing has no continuation token")]
|
||||||
MissingToken,
|
Missing,
|
||||||
#[error("truncated listing has an empty continuation token")]
|
#[error("truncated listing has an empty continuation token")]
|
||||||
EmptyToken,
|
Empty,
|
||||||
#[error("truncated listing repeats a continuation token")]
|
#[error("truncated listing repeats a continuation token")]
|
||||||
RepeatedToken,
|
Repeated,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn validate_list_page(is_truncated: bool, token: Option<&str>, next_token: Option<&str>) -> Result<(), ListPageError> {
|
pub(crate) fn validate_list_page(is_truncated: bool, token: Option<&str>, next_token: Option<&str>) -> Result<(), ListPageError> {
|
||||||
if is_truncated {
|
if is_truncated {
|
||||||
match next_token {
|
match next_token {
|
||||||
None => return Err(ListPageError::MissingToken),
|
None => return Err(ListPageError::Missing),
|
||||||
Some("") => return Err(ListPageError::EmptyToken),
|
Some("") => return Err(ListPageError::Empty),
|
||||||
Some(next) if Some(next) == token => return Err(ListPageError::RepeatedToken),
|
Some(next) if Some(next) == token => return Err(ListPageError::Repeated),
|
||||||
Some(_) => {}
|
Some(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -424,7 +424,7 @@ impl ListThroughMerger {
|
|||||||
validate_list_page(is_truncated, token.as_deref(), next_token.as_deref())?;
|
validate_list_page(is_truncated, token.as_deref(), next_token.as_deref())?;
|
||||||
// Also reject a cycle through an earlier page in this bounded fetch.
|
// Also reject a cycle through an earlier page in this bounded fetch.
|
||||||
if is_truncated && state.pages.iter().any(|page| page.token == next_token) {
|
if is_truncated && state.pages.iter().any(|page| page.token == next_token) {
|
||||||
return Err(ListPageError::RepeatedToken);
|
return Err(ListPageError::Repeated);
|
||||||
}
|
}
|
||||||
state.more = is_truncated;
|
state.more = is_truncated;
|
||||||
state.pages.push(FetchedPage {
|
state.pages.push(FetchedPage {
|
||||||
@@ -667,11 +667,11 @@ mod tests {
|
|||||||
let Some(suffix) = key.strip_prefix(prefix) else {
|
let Some(suffix) = key.strip_prefix(prefix) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(delimiter) = delimiter.filter(|delimiter| !delimiter.is_empty()) {
|
if let Some(delimiter) = delimiter.filter(|delimiter| !delimiter.is_empty())
|
||||||
if let Some((directory, _)) = suffix.split_once(delimiter) {
|
&& let Some((directory, _)) = suffix.split_once(delimiter)
|
||||||
namespace.insert(format!("{prefix}{directory}{delimiter}"), true);
|
{
|
||||||
continue;
|
namespace.insert(format!("{prefix}{directory}{delimiter}"), true);
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
namespace.insert(key.clone(), false);
|
namespace.insert(key.clone(), false);
|
||||||
}
|
}
|
||||||
@@ -765,9 +765,9 @@ mod tests {
|
|||||||
for side in [MergeSide::Local, MergeSide::Source] {
|
for side in [MergeSide::Local, MergeSide::Source] {
|
||||||
for entries in [vec![], vec![ListEntryKey::object("a")]] {
|
for entries in [vec![], vec![ListEntryKey::object("a")]] {
|
||||||
for (next, expected) in [
|
for (next, expected) in [
|
||||||
(None, Err(ListPageError::MissingToken)),
|
(None, Err(ListPageError::Missing)),
|
||||||
(Some(""), Err(ListPageError::EmptyToken)),
|
(Some(""), Err(ListPageError::Empty)),
|
||||||
(Some("stuck"), Err(ListPageError::RepeatedToken)),
|
(Some("stuck"), Err(ListPageError::Repeated)),
|
||||||
(Some("advances"), Ok(())),
|
(Some("advances"), Ok(())),
|
||||||
] {
|
] {
|
||||||
let resume = ListThroughToken::new(
|
let resume = ListThroughToken::new(
|
||||||
@@ -815,7 +815,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())),
|
merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())),
|
||||||
Err(ListPageError::RepeatedToken)
|
Err(ListPageError::Repeated)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,7 +868,7 @@ mod tests {
|
|||||||
.expect("first page advances");
|
.expect("first page advances");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
merger.push_page(MergeSide::Source, vec![], true, Some("first".into())),
|
merger.push_page(MergeSide::Source, vec![], true, Some("first".into())),
|
||||||
Err(ListPageError::RepeatedToken)
|
Err(ListPageError::Repeated)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -884,7 +884,7 @@ mod tests {
|
|||||||
assert_eq!(merger.next_fetch().expect("source refill is required").token.as_deref(), Some("stuck"));
|
assert_eq!(merger.next_fetch().expect("source refill is required").token.as_deref(), Some("stuck"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())),
|
merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())),
|
||||||
Err(ListPageError::RepeatedToken)
|
Err(ListPageError::Repeated)
|
||||||
);
|
);
|
||||||
merger.disable_source();
|
merger.disable_source();
|
||||||
let outcome = merger.finish();
|
let outcome = merger.finish();
|
||||||
|
|||||||
@@ -1338,16 +1338,16 @@ mod tests {
|
|||||||
.list_objects_v2(None, None, 10)
|
.list_objects_v2(None, None, 10)
|
||||||
.await
|
.await
|
||||||
.expect_err("truncated page without token is corrupt");
|
.expect_err("truncated page without token is corrupt");
|
||||||
assert!(matches!(err, SourceError::InvalidPagination(ListPageError::MissingToken)), "{err:?}");
|
assert!(matches!(err, SourceError::InvalidPagination(ListPageError::Missing)), "{err:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn list_page_validates_s3_cursor_progress_before_mapping_entries() {
|
async fn list_page_validates_s3_cursor_progress_before_mapping_entries() {
|
||||||
for contents in ["", "<Contents><Key>data/a</Key><Size>1</Size></Contents>"] {
|
for contents in ["", "<Contents><Key>data/a</Key><Size>1</Size></Contents>"] {
|
||||||
for (truncated, next, expected) in [
|
for (truncated, next, expected) in [
|
||||||
(true, None, Some(ListPageError::MissingToken)),
|
(true, None, Some(ListPageError::Missing)),
|
||||||
(true, Some(""), Some(ListPageError::EmptyToken)),
|
(true, Some(""), Some(ListPageError::Empty)),
|
||||||
(true, Some("stuck"), Some(ListPageError::RepeatedToken)),
|
(true, Some("stuck"), Some(ListPageError::Repeated)),
|
||||||
(true, Some("opaque-next"), None),
|
(true, Some("opaque-next"), None),
|
||||||
(false, None, None),
|
(false, None, None),
|
||||||
(false, Some("stuck"), None),
|
(false, Some("stuck"), None),
|
||||||
@@ -1420,9 +1420,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn list_page_validates_non_s3_provider_cursors_at_the_common_boundary() {
|
async fn list_page_validates_non_s3_provider_cursors_at_the_common_boundary() {
|
||||||
for (next, expected) in [
|
for (next, expected) in [
|
||||||
(None, ListPageError::MissingToken),
|
(None, ListPageError::Missing),
|
||||||
(Some(""), ListPageError::EmptyToken),
|
(Some(""), ListPageError::Empty),
|
||||||
(Some("stuck"), ListPageError::RepeatedToken),
|
(Some("stuck"), ListPageError::Repeated),
|
||||||
] {
|
] {
|
||||||
let mut client = prefix_client(Some("data/".into()));
|
let mut client = prefix_client(Some("data/".into()));
|
||||||
client.backend = Box::new(ListOnlyBackend(SourcePage {
|
client.backend = Box::new(ListOnlyBackend(SourcePage {
|
||||||
|
|||||||
Reference in New Issue
Block a user