celery/task/options.rs
1use crate::protocol::MessageContentType;
2
3/// Configuration options pertaining to a task.
4///
5/// These are set at either the app level (pertaining to all registered tasks),
6/// the task level (pertaining to a specific task), or - in some cases - at
7/// the request / signature level (pertaining only to an individual task request).
8///
9/// The order of precedence is determined by how specific the given configuration option is.
10/// That is, options set at the request level have the highest precedence,
11/// followed by options set at the task level, and lastly the app level.
12///
13/// For example, if `time_limit: Some(10)` is set at the app level through the
14/// [`task_time_limit`](crate::CeleryBuilder::task_time_limit) option,
15/// then every task will use a time limit of 10 seconds unless some other time limit is specified in the
16/// [task definition](attr.task.html#parameters) or in a
17/// [task signature](../task/struct.Signature.html#structfield.time_limit) for that task.
18#[derive(Copy, Clone, Default)]
19pub struct TaskOptions {
20 /// Time limit for a task.
21 ///
22 /// If set to `Some(n)`, the task will be interrupted and fail with a
23 /// [`TimeoutError`](error/enum.TaskError.html#variant.TimeoutError)
24 /// if it runs longer than `n` seconds.
25 ///
26 /// This can be set with
27 /// - [`task_time_limit`](crate::CeleryBuilder::task_time_limit) at the app level,
28 /// - [`time_limit`](../attr.task.html#parameters) at the task level, and
29 /// - [`with_time_limit`](crate::task::Signature::with_time_limit) at the request / signature level.
30 ///
31 /// If this option is left unspecified, the default behavior will be to enforce no time limit.
32 ///
33 /// *Note, however, that only non-blocking tasks can be interrupted, so it's important
34 /// to use async functions within task implementations whenever they are available.*
35 pub time_limit: Option<u32>,
36
37 /// The [`time_limit`](TaskOptions::time_limit) option is equivalent to the ["soft time
38 /// limit"](https://docs.celeryproject.org/en/stable/userguide/workers.html#time-limits)
39 /// option when sending tasks to a Python consumer.
40 /// If you desire to set a "hard time limit", use this option.
41 ///
42 /// *Note that this is really only for compatability with Python workers*.
43 /// `time_limit` and `hard_time_limit` are treated the same by Rust workers, and if both
44 /// are set, the minimum of the two will be used.
45 ///
46 /// This can be set with
47 /// - [`task_hard_time_limit`](crate::CeleryBuilder::task_hard_time_limit) at the app level,
48 /// - [`hard_time_limit`](../attr.task.html#parameters) at the task level, and
49 /// - [`with_hard_time_limit`](crate::task::Signature::method.with_hard_time_limit) at the request / signature level.
50 pub hard_time_limit: Option<u32>,
51
52 /// Time in seconds for when the task should expire. The task won’t be
53 /// executed after the expiration time. This can be overridden when calling the task, see
54 /// [`Signature::with_expires`](crate::task::Signature::with_expires) and
55 /// [`Signature::with_expires_in`](crate::task::Signature::with_expires_in).
56 pub expires: Option<std::time::Duration>,
57
58 /// Maximum number of retries for this task.
59 ///
60 /// This can be set with
61 /// - [`task_max_retries`](crate::CeleryBuilder::task_max_retries) at the app level, and
62 /// - [`max_retries`](../attr.task.html#parameters) at the task level.
63 ///
64 /// If this option is left unspecified, the default behavior will be to retry tasks indefinitely.
65 pub max_retries: Option<u32>,
66
67 /// Minimum retry delay (in seconds).
68 ///
69 /// This can be set with
70 /// - [`task_min_retry_delay`](crate::CeleryBuilder::task_min_retry_delay) at the app level, and
71 /// - [`min_retry_delay`](../attr.task.html#parameters) at the task level.
72 ///
73 /// If this option is left unspecified, the default behavior will be to use 0 as the
74 /// minimum. In practice this means the first retry will usually be delayed only a couple hundred milliseconds.
75 /// The delay for subsequent retries will increase exponentially (with random jitter) before
76 /// maxing out at [`max_retry_delay`](TaskOptions::max_retry_delay).
77 pub min_retry_delay: Option<u32>,
78
79 /// Maximum retry delay (in seconds).
80 ///
81 /// This can be set with
82 /// - [`task_max_retry_delay`](crate::CeleryBuilder::task_max_retry_delay) at the app level, and
83 /// - [`max_retry_delay`](../attr.task.html#parameters) at the task level.
84 ///
85 /// If this option is left unspecified, the default behavior will be to cap delays at 1 hour
86 /// (3600 seconds) with some random jitter.
87 pub max_retry_delay: Option<u32>,
88
89 /// Whether or not to retry the task when an [`UnexpectedError`](crate::error::TaskError::UnexpectedError)
90 /// is returned.
91 ///
92 /// This can be set with
93 /// - [`task_retry_for_unexpected`](crate::CeleryBuilder::task_retry_for_unexpected) at the app level, and
94 /// - [`retry_for_unexpected`](../attr.task.html#parameters) at the task level.
95 ///
96 /// If this option is left unspecified, the default behavior will be to retry for these
97 /// errors.
98 pub retry_for_unexpected: Option<bool>,
99
100 /// Whether messages will be acknowledged after the task has been executed or before.
101 ///
102 /// If your tasks are
103 /// [idempotent](https://docs.celeryproject.org/en/stable/glossary.html#term-idempotent)
104 /// then it is recommended that you set this to `true`.
105 ///
106 /// This can be set with
107 /// - [`acks_late`](crate::CeleryBuilder::acks_late) at the app level, and
108 /// - [`acks_late`](../attr.task.html#parameters) at the task level.
109 ///
110 /// If this option is left unspecified, the default behavior will be to ack early.
111 pub acks_late: Option<bool>,
112
113 /// Which serialization format to use for task messages.
114 ///
115 /// This can be set with
116 /// - [`task_content_type`](crate::CeleryBuilder::task_content_type) at the app level, and
117 /// - [`content_type`](../attr.task.html#parameters) at the task level.
118 /// - [`with_content_type`](crate::task::Signature::with_content_type) at the request / signature level.
119 pub content_type: Option<MessageContentType>,
120}
121
122impl TaskOptions {
123 /// Update the fields in `self` with the fields in `other`.
124 pub(crate) fn update(&mut self, other: &TaskOptions) {
125 self.time_limit = self.time_limit.or(other.time_limit);
126 self.hard_time_limit = self.hard_time_limit.or(other.hard_time_limit);
127 self.max_retries = self.max_retries.or(other.max_retries);
128 self.min_retry_delay = self.min_retry_delay.or(other.min_retry_delay);
129 self.max_retry_delay = self.max_retry_delay.or(other.max_retry_delay);
130 self.retry_for_unexpected = self.retry_for_unexpected.or(other.retry_for_unexpected);
131 self.acks_late = self.acks_late.or(other.acks_late);
132 self.content_type = self.content_type.or(other.content_type);
133 }
134
135 /// Override the fields in `other` with the fields in `self`.
136 pub(crate) fn override_other(&self, other: &mut TaskOptions) {
137 other.update(self);
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn test_update() {
147 let mut options = TaskOptions {
148 max_retries: Some(3),
149 acks_late: Some(true),
150 ..Default::default()
151 };
152
153 let other = TaskOptions {
154 time_limit: Some(2),
155 acks_late: Some(false),
156 ..Default::default()
157 };
158
159 options.update(&other);
160 assert_eq!(options.time_limit, Some(2));
161 assert_eq!(options.max_retries, Some(3));
162 assert_eq!(options.acks_late, Some(true));
163 }
164}