Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ resolver = "2"

[workspace.package]
edition = "2021"
version = "0.3.61"
version = "0.3.62"
description = "Tower is the best way to host Python data apps in production"
rust-version = "1.81"
authors = ["Brad Heller <brad@tower.dev>", "Ben Lovell <ben@tower.dev>"]
Expand Down
21 changes: 15 additions & 6 deletions crates/tower-cmd/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,22 @@ where
output::error(&format!("Your local run crashed with exit code: {}", code));
return Err(Error::AppCrashed);
}
Status::Failed {
error_code,
error_message,
} => {
Status::Cancelled => {
output::error("Your local run was cancelled.");
return Err(Error::AppCrashed);
}
Status::Failed(failure) => {
let detail = match failure {
tower_runtime::AppFailure::Runtime(e) => format!("{:?}", e),
tower_runtime::AppFailure::Panic(msg) => format!("panic: {}", msg),
tower_runtime::AppFailure::Platform {
error_code,
error_message,
} => format!("{} ({})", error_message, error_code),
};
output::error(&format!(
"Your local run failed due to a platform error (code: {}, message: {})",
error_code, error_message
"Your local run failed due to a platform error: {}",
detail
));
return Err(Error::AppCrashed);
}
Expand Down
1 change: 1 addition & 0 deletions crates/tower-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license = { workspace = true }
[dependencies]
async-trait = { workspace = true }
chrono = { workspace = true }
futures = { workspace = true }
nix = { workspace = true }
snafu = { workspace = true }
tmpdir = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/tower-runtime/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use snafu::prelude::*;

#[derive(Debug, Snafu)]
#[derive(Clone, Debug, PartialEq, Eq, Snafu)]
pub enum Error {
#[snafu(display("failed to RPC server"))]
RuntimeStartFailed,
Expand Down
32 changes: 30 additions & 2 deletions crates/tower-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,34 @@ pub enum Status {
Crashed {
code: i32,
},
/// The app was explicitly terminated via the `CancellationToken` — a
/// deliberate stop, not a failure or a crash. Distinct from `Crashed`
/// because there's no meaningful exit code to report.
Cancelled,
/// A platform-level failure (not the user's app). For example, pod scheduling
/// failures, image pull errors, or other infrastructure issues.
Failed {
Failed(AppFailure),
}

/// A platform-level failure — distinct from a child-process crash
/// (`Status::Crashed`) because the user's app never ran to completion.
/// Consumers (currently `tower-runtime-entrypoint` and the runner-side k8s
/// backend) translate this into the `error_code` / `error_message` strings
/// that flow through the termination-log → control-plane log pipeline.
#[derive(Clone, Debug, PartialEq)]
pub enum AppFailure {
/// A structured runtime error from `tower_runtime` (e.g.
/// `UnsupportedPlatform`, `SpawnFailed`, `DependencyInstallationFailed`).
Runtime(Error),
/// A panic inside the spawned task. `catch_unwind` only returns
/// `Box<dyn Any + Send>`, so we surface the best-effort textual payload.
Panic(String),
/// A platform failure surfaced from outside `tower_runtime` (e.g. the
/// kubelet refusing to pull an image, an init container failing, or a
/// parsed entrypoint termination message). The `error_code` is opaque
/// to `tower_runtime` — the consumer that constructed this variant owns
/// the vocabulary.
Platform {
error_code: String,
error_message: String,
},
Expand All @@ -58,7 +83,10 @@ impl Status {
pub fn is_terminal(&self) -> bool {
matches!(
self,
Status::Exited | Status::Crashed { .. } | Status::Failed { .. }
Status::Exited
| Status::Crashed { .. }
| Status::Cancelled
| Status::Failed(_)
)
}
}
Expand Down
Loading
Loading