mirror of
https://github.com/chatmail/core.git
synced 2026-05-11 19:06:29 +03:00
feat: report ready/init_error on startup via JSON-RPC notification
Why: When the deltachat-rpc-server encounters a fatal error during early startup (e.g., when the accounts directory is invalid, a file instead of a dir, or otherwise inaccessible), it exits. The Python RPC client previously lacked a structured way to wait for the server to be fully initialized or to detect early startup failures gracefully. This led to hanging tests or obscure broken pipe errors rather than clear initialization errors. How: - The RPC server now sends a JSON-RPC notification on stdout at startup: - "ready" with core_version, server_path, and accounts_dir on success - "init_error" with error message if accounts directory initialization fails - The Python RPC client reads the first line from stdout to ensure the server is ready. - The Python client raises JsonRpcError on init_error, enabling early failure detection and fast-failing rather than stalling. - Added tests to ensure the client fails immediately on invalid dirs.
This commit is contained in:
@@ -72,14 +72,7 @@ async fn main_impl() -> Result<()> {
|
||||
#[cfg(target_family = "unix")]
|
||||
let mut sigterm = signal_unix::signal(signal_unix::SignalKind::terminate())?;
|
||||
|
||||
let path = std::env::var("DC_ACCOUNTS_PATH").unwrap_or_else(|_| "accounts".to_string());
|
||||
log::info!("Starting with accounts directory `{path}`.");
|
||||
let writable = true;
|
||||
let accounts = Accounts::new(PathBuf::from(&path), writable).await?;
|
||||
|
||||
log::info!("Creating JSON-RPC API.");
|
||||
let accounts = Arc::new(RwLock::new(accounts));
|
||||
let state = CommandApi::from_arc(accounts.clone()).await;
|
||||
let (accounts, state) = init_accounts_and_report_status().await?;
|
||||
|
||||
let (client, mut out_receiver) = RpcClient::new();
|
||||
let session = RpcSession::new(client.clone(), state.clone());
|
||||
@@ -160,3 +153,41 @@ async fn main_impl() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn init_accounts_and_report_status() -> Result<(Arc<RwLock<Accounts>>, CommandApi)> {
|
||||
let path = std::env::var("DC_ACCOUNTS_PATH").unwrap_or_else(|_| "accounts".to_string());
|
||||
log::info!("Starting with accounts directory `{path}`.");
|
||||
let path = PathBuf::from(&path);
|
||||
match Accounts::new(path.clone(), true).await {
|
||||
Ok(accounts) => {
|
||||
log::info!("Creating JSON-RPC API.");
|
||||
let accounts = Arc::new(RwLock::new(accounts));
|
||||
let state = CommandApi::from_arc(accounts.clone()).await;
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(&serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "ready",
|
||||
"params": [{
|
||||
"core_version": DC_VERSION_STR,
|
||||
"server_path": env::current_exe()?.display().to_string(),
|
||||
"accounts_dir": path.display().to_string(),
|
||||
}]
|
||||
}))?
|
||||
);
|
||||
Ok((accounts, state))
|
||||
}
|
||||
Err(err) => {
|
||||
let error_msg = format!("{err:#}");
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(&serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "init_error",
|
||||
"params": [error_msg]
|
||||
}))?
|
||||
);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user