@@ -2,10 +2,10 @@ use super::capture::read_registry_value;
22use super :: helpers:: values_match;
33use crate :: error:: Error ;
44use crate :: models:: {
5- OptionInspection , RegistryAction , RegistryMismatch , ServiceMismatch , TweakDefinition ,
6- TweakInspection , TweakOption ,
5+ OptionInspection , RegistryAction , RegistryMismatch , SchedulerAction , SchedulerMismatch ,
6+ ServiceMismatch , TweakDefinition , TweakInspection , TweakOption ,
77} ;
8- use crate :: services:: { registry_service, service_control} ;
8+ use crate :: services:: { registry_service, scheduler_service , service_control} ;
99use rayon:: prelude:: * ;
1010
1111/// Inspect a tweak to find exact system state vs expected state for all options
@@ -53,9 +53,13 @@ fn inspect_option(
5353 // Check service changes
5454 let service_results = inspect_service_changes ( option) ?;
5555
56+ // Check scheduler changes
57+ let scheduler_results = inspect_scheduler_changes ( option) ?;
58+
5659 // Determine if everything matches
57- let all_match =
58- registry_results. iter ( ) . all ( |r| r. is_match ) && service_results. iter ( ) . all ( |s| s. is_match ) ;
60+ let all_match = registry_results. iter ( ) . all ( |r| r. is_match )
61+ && service_results. iter ( ) . all ( |s| s. is_match )
62+ && scheduler_results. iter ( ) . all ( |s| s. is_match ) ;
5963
6064 Ok ( OptionInspection {
6165 option_index : index,
@@ -64,6 +68,7 @@ fn inspect_option(
6468 is_pending,
6569 registry_results,
6670 service_results,
71+ scheduler_results,
6772 all_match,
6873 } )
6974}
@@ -202,3 +207,117 @@ fn inspect_service_changes(option: &TweakOption) -> Result<Vec<ServiceMismatch>,
202207
203208 Ok ( results)
204209}
210+
211+ fn inspect_scheduler_changes ( option : & TweakOption ) -> Result < Vec < SchedulerMismatch > , Error > {
212+ let mut results = Vec :: new ( ) ;
213+
214+ for change in & option. scheduler_changes {
215+ // Handle pattern-based task matching
216+ if let Some ( pattern) = & change. task_name_pattern {
217+ // For patterns, we need to list matching tasks and check each one
218+ let matching_tasks =
219+ scheduler_service:: find_tasks_by_pattern ( & change. task_path , pattern)
220+ . unwrap_or_default ( ) ;
221+
222+ if matching_tasks. is_empty ( ) && change. ignore_not_found {
223+ // Skip if no tasks found and ignore_not_found is true
224+ continue ;
225+ }
226+
227+ for task_info in matching_tasks {
228+ let actual_state = match & task_info. state {
229+ scheduler_service:: TaskState :: Ready => Some ( "Ready" . to_string ( ) ) ,
230+ scheduler_service:: TaskState :: Disabled => Some ( "Disabled" . to_string ( ) ) ,
231+ scheduler_service:: TaskState :: Running => Some ( "Running" . to_string ( ) ) ,
232+ scheduler_service:: TaskState :: NotFound => None ,
233+ scheduler_service:: TaskState :: Unknown ( s) => Some ( s. clone ( ) ) ,
234+ } ;
235+
236+ let ( expected_state, is_match) = match change. action {
237+ SchedulerAction :: Enable => {
238+ let expected = "Ready" ;
239+ let matches = matches ! (
240+ task_info. state,
241+ scheduler_service:: TaskState :: Ready
242+ | scheduler_service:: TaskState :: Running
243+ ) ;
244+ ( expected, matches)
245+ }
246+ SchedulerAction :: Disable => {
247+ let expected = "Disabled" ;
248+ let matches =
249+ matches ! ( task_info. state, scheduler_service:: TaskState :: Disabled ) ;
250+ ( expected, matches)
251+ }
252+ SchedulerAction :: Delete => {
253+ let expected = "Deleted" ;
254+ let matches =
255+ matches ! ( task_info. state, scheduler_service:: TaskState :: NotFound ) ;
256+ ( expected, matches)
257+ }
258+ } ;
259+
260+ results. push ( SchedulerMismatch {
261+ task_path : change. task_path . clone ( ) ,
262+ task_name : task_info. name ,
263+ expected_state : expected_state. to_string ( ) ,
264+ actual_state,
265+ description : format ! ( "{:?} task (pattern: {})" , change. action, pattern) ,
266+ is_match,
267+ } ) ;
268+ }
269+ } else if let Some ( task_name) = & change. task_name {
270+ // Single task inspection
271+ let task_state = scheduler_service:: get_task_state ( & change. task_path , task_name)
272+ . unwrap_or ( scheduler_service:: TaskState :: Unknown ( "Error" . to_string ( ) ) ) ;
273+
274+ // Handle not found case
275+ if matches ! ( task_state, scheduler_service:: TaskState :: NotFound )
276+ && change. ignore_not_found
277+ {
278+ continue ;
279+ }
280+
281+ let actual_state = match & task_state {
282+ scheduler_service:: TaskState :: Ready => Some ( "Ready" . to_string ( ) ) ,
283+ scheduler_service:: TaskState :: Disabled => Some ( "Disabled" . to_string ( ) ) ,
284+ scheduler_service:: TaskState :: Running => Some ( "Running" . to_string ( ) ) ,
285+ scheduler_service:: TaskState :: NotFound => None ,
286+ scheduler_service:: TaskState :: Unknown ( s) => Some ( s. clone ( ) ) ,
287+ } ;
288+
289+ let ( expected_state, is_match) = match change. action {
290+ SchedulerAction :: Enable => {
291+ let expected = "Ready" ;
292+ let matches = matches ! (
293+ task_state,
294+ scheduler_service:: TaskState :: Ready | scheduler_service:: TaskState :: Running
295+ ) ;
296+ ( expected, matches)
297+ }
298+ SchedulerAction :: Disable => {
299+ let expected = "Disabled" ;
300+ let matches = matches ! ( task_state, scheduler_service:: TaskState :: Disabled ) ;
301+ ( expected, matches)
302+ }
303+ SchedulerAction :: Delete => {
304+ let expected = "Deleted" ;
305+ let matches = matches ! ( task_state, scheduler_service:: TaskState :: NotFound ) ;
306+ ( expected, matches)
307+ }
308+ } ;
309+
310+ results. push ( SchedulerMismatch {
311+ task_path : change. task_path . clone ( ) ,
312+ task_name : task_name. clone ( ) ,
313+ expected_state : expected_state. to_string ( ) ,
314+ actual_state,
315+ description : format ! ( "{:?} task" , change. action) ,
316+ is_match,
317+ } ) ;
318+ }
319+ // If neither task_name nor task_name_pattern is set, skip this change
320+ }
321+
322+ Ok ( results)
323+ }
0 commit comments