mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-14 12:43:42 +01:00
Two users on 2026.7.x reported the app going half-dead: local editing kept
working, but Send did nothing and every encrypted secret rendered blank until
they restarted. The webview console carried a Rust task panic —
Delete task failed: task 1314 panicked with message
"Failed to get new DB connection from the pool: Error(None)"
`Error(None)` is r2d2's acquire timeout. `QueryManager::connect` and `with_tx`
turned that timeout into `expect`, so a pool that was momentarily full took down
whatever task asked for a connection instead of reporting a failure the caller
could show, retry, or ignore. Every DB-backed path shares those two functions,
which is why one stalled pool reads as "Send is dead and the secrets are gone".
Acquisition is now fallible end to end: `connect()` and `BlobManager::connect()`
return `Result`, and so do the `db()`/`blobs()` accessors on every host. Call
sites propagate with `?` where they already returned a result; the fire-and-forget
writers (streaming events, the model-change poller) log and carry on. `with_conn`
had no callers and only added a third panic, so it is gone.
Two places held a pooled connection across work that has nothing to do with the
database and can block for a long time — the OS keyring in
`EncryptionManager::get_workspace_key`, and the sync directory walk in
`cmd_sync_calculate`. Both now hand the connection back first. Those are the
paths behind the two visible symptoms.
Not fixed here: the gRPC streaming block in yaak-app-client still `.unwrap()`s
its database writes, as it did before, so acquisition failures panic there too.
`ProxyQueryManager` in the separate proxy app keeps its own `expect`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
23 lines
718 B
Rust
23 lines
718 B
Rust
use crate::context::CliContext;
|
|
|
|
pub fn resolve_workspace_id(
|
|
ctx: &CliContext,
|
|
workspace_id: Option<&str>,
|
|
command_name: &str,
|
|
) -> Result<String, String> {
|
|
if let Some(workspace_id) = workspace_id {
|
|
return Ok(workspace_id.to_string());
|
|
}
|
|
|
|
let workspaces = ctx
|
|
.db()
|
|
.map_err(|e| e.to_string())?
|
|
.list_workspaces()
|
|
.map_err(|e| format!("Failed to list workspaces: {e}"))?;
|
|
match workspaces.as_slice() {
|
|
[] => Err(format!("No workspaces found. {command_name} requires a workspace ID.")),
|
|
[workspace] => Ok(workspace.id.clone()),
|
|
_ => Err(format!("Multiple workspaces found. {command_name} requires a workspace ID.")),
|
|
}
|
|
}
|