gear_core/tasks.rs
1// This file is part of Gear.
2
3// Copyright (C) 2021-2025 Gear Technologies Inc.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! The module provides primitives for all available regular or time-dependent tasks.
20
21use crate::ids::{ActorId, CodeId, MessageId, ReservationId};
22use gsys::Gas;
23use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
24use scale_info::TypeInfo;
25
26/// Alias for ScheduledTask used in vara-runtime, generic across AccountId used.
27pub type VaraScheduledTask<AccountId> = ScheduledTask<AccountId, MessageId, bool>;
28
29/// Scheduled task sense and required data for processing action.
30///
31/// CAUTION: NEVER ALLOW `ScheduledTask` BE A BIG DATA.
32/// To avoid redundant migrations only append new variant(s) to the enum
33/// with an explicit corresponding scale codec index.
34#[derive(
35 Copy,
36 Clone,
37 Debug,
38 Eq,
39 PartialEq,
40 PartialOrd,
41 Ord,
42 Hash,
43 Encode,
44 Decode,
45 TypeInfo,
46 MaxEncodedLen,
47)]
48pub enum ScheduledTask<RFM, SD, SUM> {
49 // Rent charging section.
50 // -----
51 /// Pause program as out of rent one.
52 #[codec(index = 0)]
53 PauseProgram(ActorId),
54
55 /// Remove code from code storage as out of rent one.
56 #[codec(index = 1)]
57 RemoveCode(CodeId),
58
59 /// Remove message from mailbox as out of rent one.
60 #[codec(index = 2)]
61 RemoveFromMailbox(RFM, MessageId),
62
63 /// Remove message from waitlist as out of rent one.
64 #[codec(index = 3)]
65 RemoveFromWaitlist(ActorId, MessageId),
66
67 /// Remove paused program as dead one (issue #1014).
68 #[codec(index = 4)]
69 RemovePausedProgram(ActorId),
70
71 // Time chained section.
72 // -----
73 /// Delayed wake of the message at concrete block.
74 #[codec(index = 5)]
75 WakeMessage(ActorId, MessageId),
76
77 /// Delayed message to program sending.
78 ///
79 /// The message itself stored in DispatchStash.
80 #[codec(index = 6)]
81 SendDispatch(SD),
82
83 /// Delayed message to user sending.
84 ///
85 /// The message itself stored in DispatchStash.
86 #[codec(index = 7)]
87 SendUserMessage {
88 /// What message to send.
89 message_id: MessageId,
90 /// Should it be inserted into users mailbox.
91 to_mailbox: SUM,
92 },
93
94 /// Remove gas reservation.
95 #[codec(index = 8)]
96 RemoveGasReservation(ActorId, ReservationId),
97
98 /// Remove resume program session.
99 #[codec(index = 9)]
100 #[deprecated = "Paused program storage was removed in pallet-gear-program"]
101 RemoveResumeSession(u32),
102}
103
104impl<RFM, SD, SUM> ScheduledTask<RFM, SD, SUM> {
105 /// Processing function of current task with given handler.
106 pub fn process_with(self, handler: &mut impl TaskHandler<RFM, SD, SUM>) -> Gas {
107 use ScheduledTask::*;
108
109 match self {
110 PauseProgram(program_id) => handler.pause_program(program_id),
111 RemoveCode(code_id) => handler.remove_code(code_id),
112 RemoveFromMailbox(user_id, message_id) => {
113 handler.remove_from_mailbox(user_id, message_id)
114 }
115 RemoveFromWaitlist(program_id, message_id) => {
116 handler.remove_from_waitlist(program_id, message_id)
117 }
118 RemovePausedProgram(program_id) => handler.remove_paused_program(program_id),
119 WakeMessage(program_id, message_id) => handler.wake_message(program_id, message_id),
120 SendDispatch(message_id) => handler.send_dispatch(message_id),
121 SendUserMessage {
122 message_id,
123 to_mailbox,
124 } => handler.send_user_message(message_id, to_mailbox),
125 RemoveGasReservation(program_id, reservation_id) => {
126 handler.remove_gas_reservation(program_id, reservation_id)
127 }
128 #[allow(deprecated)]
129 RemoveResumeSession(session_id) => handler.remove_resume_session(session_id),
130 }
131 }
132}
133
134/// Task handler trait for dealing with required tasks.
135pub trait TaskHandler<RFM, SD, SUM> {
136 // Rent charging section.
137 // -----
138 /// Pause program action.
139 fn pause_program(&mut self, program_id: ActorId) -> Gas;
140 /// Remove code action.
141 fn remove_code(&mut self, code_id: CodeId) -> Gas;
142 /// Remove from mailbox action.
143 fn remove_from_mailbox(&mut self, user_id: RFM, message_id: MessageId) -> Gas;
144 /// Remove from waitlist action.
145 fn remove_from_waitlist(&mut self, program_id: ActorId, message_id: MessageId) -> Gas;
146 /// Remove paused program action.
147 fn remove_paused_program(&mut self, program_id: ActorId) -> Gas;
148
149 // Time chained section.
150 // -----
151 /// Wake message action.
152 fn wake_message(&mut self, program_id: ActorId, message_id: MessageId) -> Gas;
153
154 /// Send delayed message to program action.
155 fn send_dispatch(&mut self, stashed_message_id: SD) -> Gas;
156
157 /// Send delayed message to user action.
158 fn send_user_message(&mut self, stashed_message_id: MessageId, to_mailbox: SUM) -> Gas;
159
160 /// Remove gas reservation action.
161 fn remove_gas_reservation(&mut self, program_id: ActorId, reservation_id: ReservationId)
162 -> Gas;
163
164 /// Remove data created by resume program session.
165 fn remove_resume_session(&mut self, session_id: u32) -> Gas;
166}
167
168#[test]
169fn task_encoded_size() {
170 // We will force represent task with no more then 2^8 (256) bytes.
171 const MAX_SIZE: usize = 256;
172
173 // For example we will take `AccountId` = `ActorId` from `gear_core`.
174 assert!(VaraScheduledTask::<ActorId>::max_encoded_len() <= MAX_SIZE);
175}