eureka_mmanager/download/chapter/
task.rs1pub mod messages;
2
3use std::ops::Deref;
4
5use actix::prelude::*;
6use mangadex_api::utils::download::chapter::DownloadMode as Mode;
7use mangadex_api_schema_rust::v5::ChapterObject;
8use uuid::Uuid;
9
10use crate::{
11 download::{
12 messages::{DropSingleTaskMessage, StopTask, TaskSubscriberMessages},
13 state::{DownloadTaskState, TaskState},
14 },
15 recipients::Recipients,
16 ArcRwLock,
17};
18
19use super::ChapterDownloadManager;
20
21#[derive(Debug, Clone)]
22pub enum ChapterDownloadingState {
23 Preloading,
24 FetchingData,
25 FetchingImage {
26 filename: String,
27 index: usize,
28 len: usize,
29 },
30 FetchingAtHomeData,
31}
32
33pub type ChapterDownloadTaskState = DownloadTaskState<ChapterObject, ChapterDownloadingState>;
34
35#[derive(Debug, Clone, Copy)]
36pub enum DownloadMode {
37 Normal,
38 DataSaver,
39}
40
41impl Message for DownloadMode {
42 type Result = ();
43}
44
45impl From<DownloadMode> for Mode {
46 fn from(value: DownloadMode) -> Self {
47 match value {
48 DownloadMode::Normal => Self::Normal,
49 DownloadMode::DataSaver => Self::DataSaver,
50 }
51 }
52}
53
54impl From<Mode> for DownloadMode {
55 fn from(value: Mode) -> Self {
56 match value {
57 Mode::Normal => Self::Normal,
58 Mode::DataSaver => Self::DataSaver,
59 }
60 }
61}
62
63impl From<DownloadMode> for api_core::data_push::chapter::image::Mode {
64 fn from(value: DownloadMode) -> Self {
65 match value {
66 DownloadMode::Normal => api_core::data_push::chapter::image::Mode::Data,
67 DownloadMode::DataSaver => api_core::data_push::chapter::image::Mode::DataSaver,
68 }
69 }
70}
71
72#[derive(Debug)]
73pub struct ChapterDownloadTask {
74 id: Uuid,
75 mode: DownloadMode,
76 handle: Option<SpawnHandle>,
77 state: ArcRwLock<ChapterDownloadTaskState>,
78 manager: Addr<ChapterDownloadManager>,
79 subscribers: Recipients<TaskSubscriberMessages<ChapterDownloadTaskState>>,
80 should_stop: bool,
81 force_port_443: bool,
82}
83
84impl ChapterDownloadTask {
85 fn sync_state_subscribers(&self) {
86 self.subscribers.do_send(TaskSubscriberMessages::State(
87 self.state.read().deref().clone(),
88 ));
89 }
90}
91
92impl Drop for ChapterDownloadTask {
93 fn drop(&mut self) {
94 if !self.should_stop {
95 self.manager.do_send(DropSingleTaskMessage(self.id));
96 }
97 self.subscribers.do_send(TaskSubscriberMessages::Dropped);
98 }
99}
100
101impl Actor for ChapterDownloadTask {
102 type Context = Context<Self>;
103 fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
104 if std::convert::Into::<TaskState>::into(self.state.read().deref()).is_loading()
105 || self.subscribers.has_connection()
106 {
107 Running::Continue
108 } else {
109 Running::Stop
110 }
111 }
112}
113
114impl Handler<StopTask> for ChapterDownloadTask {
115 type Result = ();
116 fn handle(&mut self, _msg: StopTask, ctx: &mut Self::Context) -> Self::Result {
117 self.should_stop = true;
118 ctx.terminate();
119 }
120}
121
122impl ChapterDownloadTask {
123 pub(super) fn new<M: Into<DownloadMode>>(
124 id: Uuid,
125 mode: M,
126 force_port_443: bool,
127 manager: Addr<ChapterDownloadManager>,
128 ) -> Self {
129 Self {
130 id,
131 mode: mode.into(),
132 handle: None,
133 state: Default::default(),
134 subscribers: Default::default(),
135 manager,
136 should_stop: false,
137 force_port_443,
138 }
139 }
140}
141
142impl Handler<DownloadMode> for ChapterDownloadTask {
143 type Result = <DownloadMode as Message>::Result;
144 fn handle(&mut self, msg: DownloadMode, _ctx: &mut Self::Context) -> Self::Result {
145 let state = std::convert::Into::<TaskState>::into(self.state.read().deref());
146 if !state.is_loading() {
147 self.mode = msg;
148 }
149 }
150}