Skip to content

Commit f21b4f6

Browse files
committed
Make CommandContext job management methods infallible
1 parent 4362a7f commit f21b4f6

4 files changed

Lines changed: 136 additions & 177 deletions

File tree

client/src/cli.rs

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::path::Path;
55
use std::time::Duration;
66

77
use bytesize::ByteSize;
8+
use chrono::TimeDelta;
89
use humantime::format_duration;
910
use indicatif::{ProgressBar, ProgressStyle};
1011
use rustix::io::ioctl_fionread;
@@ -172,26 +173,22 @@ impl CommandContext for Cli {
172173

173174
// Job management
174175

175-
fn job_started(&mut self, job: &SignedJob) -> Result<(), CommandError> {
176+
fn job_started(&mut self, job: &SignedJob) {
176177
if let Some(session) = self.session.as_mut() {
177178
session.job_started(job.to_owned());
178-
Ok(())
179-
} else {
180-
Err(CommandError::MissingSession)
181179
}
182180
}
183181

184-
fn job_stopped(&mut self, job_id: &JobId) -> Result<(), CommandError> {
182+
fn job_stopped(&mut self, job_id: &JobId) {
185183
match self.get_output_format() {
186184
OutputFormat::Json => println!("{}", json!(job_id)),
187185
OutputFormat::Text => println!("✅ Stopped job `{job_id}`"),
188186
}
189-
Ok(())
190187
}
191188

192-
fn job_error(&mut self, error: CommandError) -> Result<(), CommandError> {
189+
fn job_error(&mut self, error: CommandError) -> CommandError {
193190
eprintln!("{error}");
194-
Ok(())
191+
error
195192
}
196193

197194
fn job_output(
@@ -200,30 +197,29 @@ impl CommandContext for Cli {
200197
stream: JobOutputStream,
201198
output: &[u8],
202199
binary: bool,
203-
) -> Result<(), CommandError> {
200+
) {
204201
match self.get_output_format() {
205202
OutputFormat::Json if binary => println!("{}", json!(output)),
206-
OutputFormat::Json => println!("{}", json!(String::from_utf8(output.to_vec())?)),
203+
OutputFormat::Json => println!("{}", json!(String::from_utf8_lossy(output))),
207204
OutputFormat::Text if binary => {
208-
stdout()
209-
.write(output)
210-
.map_err(|error| CommandError::io("stdout", error))?;
205+
if let Err(err) = stdout().write_all(output) {
206+
eprintln!("{err}");
207+
}
211208
}
212209
OutputFormat::Text if output.is_empty() => (),
213210
OutputFormat::Text => {
214211
match stream {
215212
JobOutputStream::Stdout => println!("✅ Job stdout:"),
216213
JobOutputStream::Stderr => println!("✅ Job stderr:"),
217214
};
218-
let output = String::from_utf8(output.to_vec())?;
215+
let output = String::from_utf8_lossy(output);
219216
if output.ends_with('\n') {
220217
print!("{output}");
221218
} else {
222219
println!("{output}");
223220
}
224221
}
225222
}
226-
Ok(())
227223
}
228224

229225
fn job_output_started(
@@ -232,7 +228,7 @@ impl CommandContext for Cli {
232228
stream: JobOutputStream,
233229
stage: &str,
234230
total_length: u64,
235-
) -> Result<(), CommandError> {
231+
) {
236232
if matches!(self.get_output_format(), OutputFormat::Text) && self.progress.is_none() {
237233
let bar = ProgressBar::new(total_length);
238234
bar.set_prefix(format!("{stage} {stream}"));
@@ -248,27 +244,20 @@ impl CommandContext for Cli {
248244
);
249245
self.progress = Some(bar);
250246
}
251-
Ok(())
252247
}
253248

254-
fn job_output_update(
255-
&mut self,
256-
_id: &JobId,
257-
_stream: JobOutputStream,
258-
length: u64,
259-
) -> Result<(), CommandError> {
249+
fn job_output_update(&mut self, _id: &JobId, _stream: JobOutputStream, length: u64) {
260250
if let Some(progress) = &mut self.progress {
261251
progress.inc(length);
262252
}
263-
Ok(())
264253
}
265254

266255
fn job_output_finished(
267256
&mut self,
268257
_job_id: &JobId,
269258
stream: JobOutputStream,
270259
stage: Option<&str>,
271-
) -> Result<(), CommandError> {
260+
) {
272261
if let Some(progress) = self.progress.take() {
273262
progress.finish_and_clear();
274263
if let Some(stage) = stage {
@@ -282,14 +271,9 @@ impl CommandContext for Cli {
282271
);
283272
}
284273
}
285-
Ok(())
286274
}
287275

288-
fn job_polling_started(
289-
&mut self,
290-
job_id: &JobId,
291-
elapsed: Duration,
292-
) -> Result<(), CommandError> {
276+
fn job_polling_started(&mut self, job_id: &JobId, elapsed: Duration) {
293277
if matches!(self.get_output_format(), OutputFormat::Text) && self.progress.is_none() {
294278
let bar = ProgressBar::new_spinner();
295279
bar.set_elapsed(elapsed);
@@ -305,14 +289,9 @@ impl CommandContext for Cli {
305289
);
306290
self.progress = Some(bar);
307291
}
308-
Ok(())
309292
}
310293

311-
fn job_polling_update(
312-
&mut self,
313-
_job_id: &JobId,
314-
status: &JobStatus,
315-
) -> Result<(), CommandError> {
294+
fn job_polling_update(&mut self, _job_id: &JobId, status: &JobStatus) {
316295
if let Some(progress) = &mut self.progress {
317296
if let JobStatus::Started {
318297
stdout_len,
@@ -331,33 +310,29 @@ impl CommandContext for Cli {
331310
}
332311
progress.tick();
333312
}
334-
Ok(())
335313
}
336314

337-
fn job_polling_finished(&mut self, _job_id: &JobId) -> Result<(), CommandError> {
315+
fn job_polling_finished(&mut self, _job_id: &JobId) {
338316
if let Some(progress) = self.progress.take() {
339317
progress.finish_and_clear();
340318
}
341-
Ok(())
342319
}
343320

344-
fn job_session_connected(&mut self, job_id: &JobId) -> Result<(), CommandError> {
321+
fn job_session_connected(&mut self, job_id: &JobId) {
345322
match self.get_output_format() {
346323
OutputFormat::Json => println!("{}", json!({"connected": job_id})),
347324
OutputFormat::Text => println!("✅ Connected to interactive job `{job_id}`"),
348325
}
349-
Ok(())
350326
}
351327

352-
fn job_session_disconnected(&mut self, job_id: &JobId) -> Result<(), CommandError> {
328+
fn job_session_disconnected(&mut self, job_id: &JobId) {
353329
match self.get_output_format() {
354330
OutputFormat::Json => println!("{}", json!({"disconnected": job_id})),
355331
OutputFormat::Text => println!("\r✅ Disconnected interactive job `{job_id}`"),
356332
}
357-
Ok(())
358333
}
359334

360-
fn job_signing_started(&mut self, job_id: &JobId) -> Result<(), CommandError> {
335+
fn job_signing_started(&mut self, job_id: &JobId) {
361336
if matches!(self.get_output_format(), OutputFormat::Text) && self.progress.is_none() {
362337
let bar = ProgressBar::new_spinner();
363338
bar.set_prefix(format!("Waiting for signature on `{job_id}`"));
@@ -373,37 +348,52 @@ impl CommandContext for Cli {
373348
bar.enable_steady_tick(Duration::from_millis(100));
374349
self.progress = Some(bar);
375350
}
376-
Ok(())
377351
}
378352

379-
fn job_signing_update(&mut self, _job_id: &JobId) -> Result<(), CommandError> {
353+
fn job_signing_update(&mut self, _job_id: &JobId) {
380354
if let Some(progress) = &mut self.progress {
381355
progress.tick();
382356
}
383-
Ok(())
384357
}
385358

386-
fn job_signing_finished(&mut self, job_id: &JobId) -> Result<(), CommandError> {
359+
fn job_signing_finished(&mut self, job_id: &JobId) {
387360
if let Some(progress) = self.progress.take() {
388361
progress.finish_and_clear();
389362
}
390363
if matches!(self.get_output_format(), OutputFormat::Text) {
391364
println!("✅ Signed request for job `{job_id}`");
392365
}
393-
Ok(())
394366
}
395367

396-
fn job_signed(&mut self, job: &SignedJob, show: bool) -> Result<(), CommandError> {
368+
fn job_signed(&mut self, job: &SignedJob, show: bool) {
397369
if show {
398370
match self.get_output_format() {
399-
OutputFormat::Json => println!("{}", to_json_string(&job)?),
400-
OutputFormat::Text => println!("{}", to_json_string_pretty(&job)?),
371+
OutputFormat::Json => println!(
372+
"{}",
373+
to_json_string(&job).expect("job should be JSON-serializable")
374+
),
375+
OutputFormat::Text => println!(
376+
"{}",
377+
to_json_string_pretty(&job).expect("job should be JSON-serializable")
378+
),
401379
}
402380
}
403-
Ok(())
404381
}
405382

406-
fn job_status(&mut self, job_id: &JobId, status: &JobStatus) -> Result<(), CommandError> {
383+
fn job_status(&mut self, job_id: &JobId, status: &JobStatus) {
384+
fn format_elapsed_duration(duration: Option<TimeDelta>) -> String {
385+
match duration {
386+
None => String::from("empty duration"),
387+
Some(duration) => {
388+
if let Ok(duration) = duration.to_std() {
389+
format_duration(duration).to_string()
390+
} else {
391+
String::from("negative duration, times may be unreliable")
392+
}
393+
}
394+
}
395+
}
396+
407397
match self.get_output_format() {
408398
OutputFormat::Json => println!("{}", json!(status)),
409399
OutputFormat::Text => match status {
@@ -444,7 +434,7 @@ impl CommandContext for Cli {
444434
stderr_hash,
445435
} => {
446436
let command = job.command();
447-
let duration = format_duration(status.time_elapsed().unwrap().to_std()?);
437+
let duration = format_elapsed_duration(status.time_elapsed());
448438
let stdout_len = byte_size(*stdout_len);
449439
let stderr_len = byte_size(*stderr_len);
450440
println!(
@@ -473,7 +463,7 @@ impl CommandContext for Cli {
473463
stderr_hash,
474464
} => {
475465
let command = job.command();
476-
let duration = format_duration(status.time_elapsed().unwrap().to_std()?);
466+
let duration = format_elapsed_duration(status.time_elapsed());
477467
let stdout_len = byte_size(*stdout_len);
478468
let stderr_len = byte_size(*stderr_len);
479469
println!(
@@ -491,7 +481,6 @@ impl CommandContext for Cli {
491481
}
492482
},
493483
}
494-
Ok(())
495484
}
496485

497486
fn read_signed_job(&mut self) -> Result<SignedJob, CommandError> {

0 commit comments

Comments
 (0)