-
Notifications
You must be signed in to change notification settings - Fork 443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
storage controller: read from database in validate API #8784
Conversation
3829 tests run: 3719 passed, 0 failed, 110 skipped (full report)Flaky tests (4)Postgres 16
Postgres 15
Postgres 14
Code coverage* (full report)
* collected from Rust tests only The comment gets automatically updated with the latest test results
dc462a8 at 2024-09-04T12:04:17.575Z :recycle: |
425dae1
to
0f3f5cc
Compare
53ed5fa
to
75b44f9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While reviewing this PR, I was wondering about the legitimacy of omitting tenants from the response, and found that storage_controller doesn't have an OpenAPI yaml. Maybe we should have that? The only docs for /validate
behavior is in the RFC, and by reading the code that uses it in deletion_queue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Batching of 32 means a call with 10k tenants will be ~313 queries; conservatively 100ms per query yields 31 seconds of validate call duration. Would our client timeouts trip over this?
Looking at how we construct the client, I guess we get whathever the default reqwest timeout is:
neon/pageserver/src/control_plane_client.rs
Lines 63 to 79 in 793b506
let mut client = reqwest::ClientBuilder::new(); | |
if let Some(jwt) = &conf.control_plane_api_token { | |
let mut headers = reqwest::header::HeaderMap::new(); | |
headers.insert( | |
"Authorization", | |
format!("Bearer {}", jwt.get_contents()).parse().unwrap(), | |
); | |
client = client.default_headers(headers); | |
} | |
Some(Self { | |
http_client: client.build().expect("Failed to construct HTTP client"), | |
base_url: url, | |
node_id: conf.id, | |
cancel: cancel.clone(), | |
}) |
I'm going to merge this today to get the critical fix in, and then do a followup that chunks up validation requests from clients -- right now we pretty much assume they don't get into a situation where the deletion queue really needs to validate 10k tenants at once, but we should avoid letting that hang around as a "load bearing assumption". |
…8997) ## Problem - In #8784, the validate controller API is modified to check generations directly in the database. It batches tenants into separate queries to avoid generating a huge statement, but - While updating this, I realized that "control_plane_client" is a kind of confusing name for the client code now that it primarily talks to the storage controller (the case of talking to the control plane will go away in a few months). ## Summary of changes - Big rename to "ControllerUpcallClient" -- this reflects the storage controller's api naming, where the paths used by the pageserver are in `/upcall/` - When sending validate requests, break them up into chunks so that we avoid possible edge cases of generating any HTTP requests that require database I/O across many thousands of tenants. This PR mixes a functional change with a refactor, but the commits are cleanly separated -- only the last commit is a functional change. --------- Co-authored-by: Christian Schwarz <christian@neon.tech>
…8997) ## Problem - In #8784, the validate controller API is modified to check generations directly in the database. It batches tenants into separate queries to avoid generating a huge statement, but - While updating this, I realized that "control_plane_client" is a kind of confusing name for the client code now that it primarily talks to the storage controller (the case of talking to the control plane will go away in a few months). ## Summary of changes - Big rename to "ControllerUpcallClient" -- this reflects the storage controller's api naming, where the paths used by the pageserver are in `/upcall/` - When sending validate requests, break them up into chunks so that we avoid possible edge cases of generating any HTTP requests that require database I/O across many thousands of tenants. This PR mixes a functional change with a refactor, but the commits are cleanly separated -- only the last commit is a functional change. --------- Co-authored-by: Christian Schwarz <christian@neon.tech>
Problem
The initial implementation of the validate API treats the in-memory generations as authoritative.
Summary of changes
test_storage_controller_validate_during_migration
, which uses failpoints to create a situation where incorrect generation validation during a live migration could result in a corruptionThe rate of validate calls for tenants is pretty low: it happens as a consequence deletions from GC and compaction, which are both concurrency-limited on the pageserver side.
Checklist before requesting a review
Checklist before merging