Repository navigation
feat(grpc): add FlushCache and profile RPCs with worker-abstracted admin ops #1655
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -995,9 +995,64 @@ pub struct FlushCacheResult { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub failed: Vec<(String, String)>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub total_workers: usize, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub http_workers: usize, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub grpc_workers: usize, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub message: String, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Options for starting a profiling run on workers. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Mirrors the engines' native profile parameters: serialized verbatim as | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// the JSON body for HTTP workers and mapped to the `StartProfile` RPC for | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// gRPC workers. Unset fields fall back to backend defaults. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Clone, Default, Serialize, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct ProfileOptions { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub output_dir: Option<String>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub start_step: Option<i32>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub num_steps: Option<i32>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub activities: Option<Vec<String>>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub with_stack: Option<bool>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub record_shapes: Option<bool>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub profile_by_stage: bool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1008
to
+1024
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested fix #[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct ProfileOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub output_dir: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_step: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub num_steps: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub activities: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub with_stack: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub record_shapes: Option<bool>,
- pub profile_by_stage: bool,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub profile_by_stage: Option<bool>,
}Based on PR context, unset profile parameters are supposed to defer to backend defaults. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Result from profile start/stop operations across workers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Clone, Deserialize, Serialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct ProfileResult { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub successful: Vec<String>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub failed: Vec<(String, String)>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub total_workers: usize, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub message: String, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Request body for the gateway `/start_profile` route: profile options | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// plus an optional worker URL to target a single worker (e.g. one | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// PD-disaggregation role). All workers are profiled when `url` is unset. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Clone, Default, Serialize, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct StartProfileRequest { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub url: Option<String>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(flatten)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub options: ProfileOptions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Request body for the gateway `/stop_profile` route: optional worker URL | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// to target a single worker. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Clone, Default, Serialize, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct StopProfileRequest { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub url: Option<String>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Result from getting worker loads | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Clone, Deserialize, Serialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct WorkerLoadsResult { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1101,6 +1156,43 @@ impl IntoResponse for FlushCacheResult { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "message": self.message, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "workers_flushed": self.successful.len(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "total_http_workers": self.http_workers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "total_grpc_workers": self.grpc_workers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "total_workers": self.total_workers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !self.failed.is_empty() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| body["successful"] = json!(self.successful); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| body["failed"] = json!(self | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .failed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .into_iter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(|(url, err)| json!({"worker": url, "error": err})) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .collect::<Vec<_>>()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (status, Json(body)).into_response() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "axum")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl IntoResponse for ProfileResult { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn into_response(self) -> Response { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let status = if self.total_workers == 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StatusCode::NOT_FOUND | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if self.failed.is_empty() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StatusCode::OK | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StatusCode::PARTIAL_CONTENT | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let status_str = match status { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StatusCode::OK => "success", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StatusCode::PARTIAL_CONTENT => "partial_success", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ => "error", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut body = json!({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "status": status_str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "message": self.message, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "workers_profiled": self.successful.len(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "total_workers": self.total_workers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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.
Using
std::time::Duration::from_secs_f32directly ontimeout_s.max(0.0)can cause a panic iftimeout_sisNaNorInfinity(sincefrom_secs_f32panics on non-finite values). To prevent potential denial-of-service panics, sanitizetimeout_sto ensure it is finite before converting it to aDuration.References