coven_sync/file_upload_queue.rs
1//! The upload queue as the app observes it (E7): the committed queue, with
2//! the uploads this process is sending now.
3
4pub use coven_database::UploadProgress;
5use coven_database::UploadQueueState;
6use coven_foundation::id_source::FileId;
7use std::time::SystemTime;
8
9/// Observable upload queue state (E7): one committed snapshot of the queue,
10/// with the uploads this process is sending as it is read.
11#[derive(Clone, Debug, PartialEq)]
12pub struct UploadQueue {
13 /// Whether transfer work is paused; persisted across reopening.
14 pub paused: bool,
15 /// Waiting files, oldest first. Files sharing one upload share its
16 /// place and progress.
17 pub files: Vec<QueuedUpload>,
18}
19/// One queued upload: whether it is being sent, and its committed progress.
20#[derive(Clone, Debug, PartialEq)]
21pub struct QueuedUpload {
22 /// The file its upload switches to the cloud.
23 pub file: FileId,
24 /// Whether this device is sending the file now.
25 pub phase: UploadPhase,
26 /// Progress the provider confirmed and this device persisted in the
27 /// file's resumable session; `None` while it has no session, as a file
28 /// sent in one request never does.
29 pub progress: Option<UploadProgress>,
30 /// Enqueue time.
31 pub queued_at: SystemTime,
32}
33/// Whether a queued file is being sent. Nothing about it is persisted: a
34/// reopened store starts with every file waiting.
35#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub enum UploadPhase {
37 /// Not being sent: not started yet, paused, waiting for a free upload
38 /// slot or for its retry, or stored, waiting for the rest of its move
39 /// (ยง17.3).
40 Waiting,
41 /// An attempt is sending it now, in one request or in parts.
42 Uploading,
43}
44
45impl From<UploadQueueState> for UploadQueue {
46 /// Each file this process was sending as the queue was read is
47 /// uploading, beside the confirmed bytes its recorded session holds.
48 fn from(state: UploadQueueState) -> Self {
49 let files = state
50 .uploads
51 .into_iter()
52 .flat_map(|upload| {
53 let sending = &state.sending;
54 upload
55 .files
56 .iter()
57 .map(move |file| QueuedUpload {
58 phase: if sending.contains(file) {
59 UploadPhase::Uploading
60 } else {
61 UploadPhase::Waiting
62 },
63 file: *file,
64 progress: upload.progress,
65 queued_at: upload.queued_at,
66 })
67 .collect::<Vec<_>>()
68 })
69 .collect();
70 Self { paused: state.paused, files }
71 }
72}