mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-12 15:02:32 +00:00
test(client): inline retry hint compatibility cases
Signed-off-by: WenyXu <wenymedia@gmail.com>
This commit is contained in:
Generated
-1
@@ -2115,7 +2115,6 @@ dependencies = [
|
||||
"prost 0.14.1",
|
||||
"query",
|
||||
"rand 0.9.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"snafu 0.8.6",
|
||||
"store-api",
|
||||
|
||||
@@ -46,6 +46,3 @@ tokio.workspace = true
|
||||
tokio-stream = { workspace = true, features = ["net"] }
|
||||
tonic.workspace = true
|
||||
tonic-prost.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
serde.workspace = true
|
||||
|
||||
+23
-28
@@ -666,19 +666,25 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_retry_hint_wire_compatibility() {
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Fixture {
|
||||
name: String,
|
||||
wire_hint: Option<String>,
|
||||
expected_hint: String,
|
||||
}
|
||||
|
||||
let fixtures: Vec<Fixture> = serde_json::from_str(include_str!(
|
||||
"../../../tests/compatibility/wire/write_retry/retry_hints.json"
|
||||
))
|
||||
.unwrap();
|
||||
assert_eq!(fixtures.len(), 5);
|
||||
for fixture in fixtures {
|
||||
for (name, wire_hint, expected_hint) in [
|
||||
("legacy_missing", None, RetryHint::NonRetryable),
|
||||
("legacy_retryable", Some("retryable"), RetryHint::Retryable),
|
||||
(
|
||||
"legacy_non_retryable",
|
||||
Some("non_retryable"),
|
||||
RetryHint::NonRetryable,
|
||||
),
|
||||
(
|
||||
"route_refresh",
|
||||
Some("retry_after_route_refresh"),
|
||||
RetryHint::RetryAfterRouteRefresh,
|
||||
),
|
||||
(
|
||||
"unknown_future_hint",
|
||||
Some("future_retry_hint"),
|
||||
RetryHint::NonRetryable,
|
||||
),
|
||||
] {
|
||||
let mut status = Status::failed_precondition("region unavailable");
|
||||
status.metadata_mut().insert(
|
||||
common_error::GREPTIME_DB_HEADER_ERROR_CODE,
|
||||
@@ -687,30 +693,19 @@ mod tests {
|
||||
.parse()
|
||||
.unwrap(),
|
||||
);
|
||||
if let Some(hint) = fixture.wire_hint {
|
||||
if let Some(hint) = wire_hint {
|
||||
status.metadata_mut().insert(
|
||||
common_error::GREPTIME_DB_HEADER_ERROR_RETRY_HINT,
|
||||
hint.parse().unwrap(),
|
||||
);
|
||||
}
|
||||
let error: error::Error = status.into();
|
||||
assert_eq!(
|
||||
error.retry_hint().as_str(),
|
||||
fixture.expected_hint,
|
||||
"{}",
|
||||
fixture.name
|
||||
);
|
||||
assert_eq!(
|
||||
error.status_code(),
|
||||
StatusCode::RegionNotReady,
|
||||
"{}",
|
||||
fixture.name
|
||||
);
|
||||
assert_eq!(error.retry_hint(), expected_hint, "{name}");
|
||||
assert_eq!(error.status_code(), StatusCode::RegionNotReady, "{name}");
|
||||
assert_eq!(
|
||||
error.tonic_code(),
|
||||
Some(tonic::Code::FailedPrecondition),
|
||||
"{}",
|
||||
fixture.name
|
||||
"{name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ SQL restart tests are run via `cargo sqlness compat` and reuse the sqlness-runne
|
||||
|
||||
## Wire fixtures
|
||||
|
||||
Frozen wire fixtures are exercised by the Rust tests that own their context
|
||||
Frozen protobuf fixtures are exercised by the Rust tests that own their context
|
||||
conversion, not by SQLness case discovery. The
|
||||
[legacy query-context fixture](wire/read_preference/README.md) checks omitted
|
||||
read-preference defaulting and unrelated metadata preservation:
|
||||
@@ -15,13 +15,6 @@ read-preference defaulting and unrelated metadata preservation:
|
||||
cargo nextest run -p session -E 'test(test_legacy_query_context_wire_defaults_to_leader)'
|
||||
```
|
||||
|
||||
The [write-retry metadata fixture](wire/write_retry/README.md) checks legacy,
|
||||
route-refresh, missing, and unknown retry-hint decoding in the client:
|
||||
|
||||
```shell
|
||||
cargo nextest run -p client -E 'test(test_retry_hint_wire_compatibility)'
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```shell
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# Write-retry metadata compatibility
|
||||
|
||||
`retry_hints.json` freezes gRPC `x-greptime-err-retry-hint` metadata values
|
||||
and the expected current client decoding. These are constructed protocol fixtures,
|
||||
not captures from released binaries.
|
||||
|
||||
The client test converts real `tonic::Status` metadata through the production
|
||||
error decoder. Missing and unknown values default to `NonRetryable`; existing
|
||||
`retryable` and `non_retryable` values retain their meaning; the new
|
||||
`retry_after_route_refresh` value preserves its distinct hint. The application
|
||||
status code and gRPC status code remain unchanged.
|
||||
|
||||
```shell
|
||||
cargo nextest run -p client -E 'test(test_retry_hint_wire_compatibility)'
|
||||
```
|
||||
|
||||
`test_transport_error_parity_and_datanode_mapping` separately exercises these
|
||||
recognized values over an actual gRPC client/server connection.
|
||||
|
||||
An older decoder that recognizes only the two legacy strings treats the new
|
||||
string as unknown and uses its existing `NonRetryable` fallback. This is a source
|
||||
compatibility observation, not a claim that an old binary was run. These tests do
|
||||
not promise that an old client will refresh routing or perform automatic retries.
|
||||
|
||||
The fixture is hand-authored and must not be regenerated from test output.
|
||||
@@ -1,7 +0,0 @@
|
||||
[
|
||||
{"name": "legacy_missing", "wire_hint": null, "expected_hint": "non_retryable"},
|
||||
{"name": "legacy_retryable", "wire_hint": "retryable", "expected_hint": "retryable"},
|
||||
{"name": "legacy_non_retryable", "wire_hint": "non_retryable", "expected_hint": "non_retryable"},
|
||||
{"name": "route_refresh", "wire_hint": "retry_after_route_refresh", "expected_hint": "retry_after_route_refresh"},
|
||||
{"name": "unknown_future_hint", "wire_hint": "future_retry_hint", "expected_hint": "non_retryable"}
|
||||
]
|
||||
Reference in New Issue
Block a user