[wip] impl Client for ureq::Agent

- progress bar handling
- share notify timing
This commit is contained in:
Jörn-Michael Miehe 2025-06-12 22:26:48 +00:00
parent 2edc690331
commit b9a0e1eeb0
2 changed files with 54 additions and 26 deletions

View file

@ -1,4 +1,8 @@
use std::{fmt, io, time::Duration}; use std::{
cell::{Ref, RefCell},
fmt, io,
time::Duration,
};
use console::style; use console::style;
use indicatif::{ProgressBar, ProgressStyle}; use indicatif::{ProgressBar, ProgressStyle};
@ -7,12 +11,12 @@ use log::debug;
use super::{ use super::{
cachefile::CacheFile, cachefile::CacheFile,
cli::Cli, cli::Cli,
file::FileTrait, file::{self, FileTrait},
sharry::{self, Client, ClientError}, sharry::{self, Client, ClientError},
}; };
pub struct AppState { pub struct AppState {
progress: Option<ProgressBar>, current_bar: RefCell<Option<ProgressBar>>,
buffer: Vec<u8>, buffer: Vec<u8>,
inner: CacheFile, inner: CacheFile,
@ -29,7 +33,7 @@ impl fmt::Debug for AppState {
impl AppState { impl AppState {
fn new(chunk_size: usize, inner: CacheFile) -> Self { fn new(chunk_size: usize, inner: CacheFile) -> Self {
Self { Self {
progress: None, current_bar: None.into(),
buffer: vec![0; chunk_size * 1024 * 1024], buffer: vec![0; chunk_size * 1024 * 1024],
inner, inner,
} }
@ -56,16 +60,9 @@ impl AppState {
)) ))
} }
pub fn upload_chunk(&mut self, http: &impl Client) -> sharry::Result<Option<()>> { fn get_or_create_progressbar(&self, uploading: &file::Uploading) -> Ref<'_, ProgressBar> {
let Some(mut uploading) = self.inner.pop_file(http) else { let mut slot = self.current_bar.borrow_mut();
return Ok(None); if slot.is_none() {
};
debug!("{uploading} chunk {}", self.buffer.len());
// Initialize or fetch the existing ProgressBar
let bar = &*self.progress.get_or_insert_with(|| {
// Create a new bar with style
let bar = ProgressBar::new(uploading.get_size()) let bar = ProgressBar::new(uploading.get_size())
.with_style( .with_style(
ProgressStyle::with_template(&format!( ProgressStyle::with_template(&format!(
@ -76,21 +73,42 @@ impl AppState {
), ),
style("/").magenta(), style("/").magenta(),
)) ))
.unwrap(), .unwrap(), // safe as long as the style template is valid
) )
.with_message(uploading.get_name().to_owned()) .with_position(uploading.get_offset())
.with_position(uploading.get_offset()); .with_message(uploading.get_name().to_owned());
bar.enable_steady_tick(Duration::from_millis(100)); bar.enable_steady_tick(Duration::from_millis(100));
bar *slot = Some(bar);
}); }
drop(slot);
// unwrap is safe: We just made sure it's `Some`.
Ref::map(self.current_bar.borrow(), |opt| opt.as_ref().unwrap())
}
fn finish_bar(&self) {
let mut slot = self.current_bar.borrow_mut();
if let Some(bar) = &*slot {
bar.finish();
*slot = None;
}
}
pub fn upload_chunk(&mut self, http: &impl Client) -> sharry::Result<Option<()>> {
let Some(mut uploading) = self.inner.pop_file(http) else {
self.inner.share_notify(http).unwrap(); // HACK unwrap
return Ok(None);
};
self.get_or_create_progressbar(&uploading);
debug!("{uploading} chunk {}", self.buffer.len());
let chunk = uploading let chunk = uploading
.read(&mut self.buffer) .read(&mut self.buffer)
.map_err(ClientError::from)?; .map_err(ClientError::from)?;
if chunk.get_length() == 0 {
return Err(ClientError::req_err("wtf"));
}
http.file_patch( http.file_patch(
chunk.get_patch_uri(), chunk.get_patch_uri(),
@ -101,16 +119,19 @@ impl AppState {
match uploading.check_eof() { match uploading.check_eof() {
Ok(uploading) => { Ok(uploading) => {
let bar = self.get_or_create_progressbar(&uploading);
bar.set_position(uploading.get_offset()); bar.set_position(uploading.get_offset());
// BUG in `indicatif` crate?
// `set_position` does not force immediate redraw, so we also call `inc_length` here
bar.inc_length(0);
drop(bar);
self.inner.push_file(uploading); self.inner.push_file(uploading);
Ok(Some(())) Ok(Some(()))
} }
Err(path) => { Err(path) => {
debug!("Finished {:?}!", path.display()); debug!("Finished {:?}!", path.display());
bar.finish(); self.finish_bar();
self.progress = None;
self.inner.share_notify(http).unwrap(); // HACK unwrap
Ok(self.inner.has_file().then_some(())) Ok(self.inner.has_file().then_some(()))
} }

View file

@ -48,6 +48,13 @@ impl Uploading {
f.seek(SeekFrom::Start(self.offset))?; f.seek(SeekFrom::Start(self.offset))?;
let read_len = f.read(buf)?; let read_len = f.read(buf)?;
if read_len == 0 {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
format!("could not read from file {:?}", self.path.display()),
));
}
let chunk = Chunk::new(&buf[..read_len], &self.patch_uri, self.offset); let chunk = Chunk::new(&buf[..read_len], &self.patch_uri, self.offset);
self.offset += chunk.get_length(); self.offset += chunk.get_length();