''i&SrSSKrSSKrSSKrSSKJr SSKJr SSKJr SSK J r SSK J r SSK Jr SS KJr SS KJr SS KJr SS KJr SS KJr "SS5rSr\S:Xa\"5 gg)zw Scheduler Daemon for Python Scheduler Main daemon process that manages job scheduling and execution using APScheduler N)Optional)datetime)BackgroundScheduler) CronTrigger)IntervalTrigger) DateTrigger)logger)SchedulerDatabase)SchedulerConfig) setup_logging) JobExecutorc\rSrSrSrSrSrSrSrSr S\ 4S jr S \ S \ 4S jr S \4SjrSrS \4SjrS \4SjrS \S\\4SjrS\ 4SjrSrg)SchedulerDaemonz'Main scheduler daemon using APSchedulerc[S5 [R"S5 [5Ul[ URR 5Ul[URUR5Ul [SSSSS.S9Ul S Ul [R"[RUR5 [R"[R UR5 [R"S 5 g) NdaemonzInitializing Scheduler Daemonz Europe/RomeTi,)coalesce max_instancesmisfire_grace_time)timezone job_defaultsFzScheduler Daemon initialized)r r infor configr database_pathdbr executorr schedulerrunningsignalSIGINT_signal_handlerSIGTERM)selfs .c:\PYTHON\Scheduler\daemon\scheduler_daemon.py__init__SchedulerDaemon.__init__sh 34&' $DKK$=$=>$DGGT[[9 -" !"&)    fmmT%9%9: fnnd&:&:; 23cX[R"SUS35 UR5 g)zHandle shutdown signalszReceived signal z, shutting down...N)r rshutdown)r$signumframes r%r"SchedulerDaemon._signal_handler;s" &vh.@AB r(c[R"S5 UR5 URR 5 SUl[R"S5 [R"S[ URR55S35 UR (aS[R"URRSS55 UR5 UR (aMSUR!5 g ![a [R"S5 N3f=f![an[R"S U35 eS nAff=f!UR!5 f=f) zStart the scheduler daemonzStarting Scheduler DaemonTz%Scheduler Daemon started successfullyzLoaded z scheduled jobszdaemon.check_interval_secondszKeyboard interrupt receivedzError starting daemon: N)r r _load_jobsrstartrlenget_jobstimesleeprget _health_checkKeyboardInterrupt Exception exceptionr*)r$es r%r1SchedulerDaemon.start@s  /0  OO  NN "DL KK? @ KK'#dnn&=&=&?"@!AQ R ;llJJt{{/NPRST&&( lll MMO% ; 9: ;    6qc: ;   MMOsIBD6A"D D30D61E"2D33D66 EEEE""E4cUR(dg[R"S5 SUlURR(a/URR SS9 [R"S5 UR R 5nU(a[R"S[U5S35 S n[R"5nU(aq[R"5U- U:aU[R"S 5 UR R 5nU(a[R"5U- U:aMUU(a"[R"[U5S 35 [R"S 5 g) zShutdown the daemon gracefullyNzShutting down Scheduler DaemonFT)waitzAPScheduler stoppedz Waiting for z active jobs to complete...<rz! jobs still running after timeoutzScheduler Daemon stopped) rr rrr*rget_active_executionsr2r4r5warning)r$activetimeoutr1s r%r*SchedulerDaemon.shutdownas||  45  >> ! ! NN # # # . KK- .446  KK,s6{m3NO PGIIKEdiikE1W< 1 <<>diikE1W<#f+.OPQ ./r(c URRSS9n[R"S[ U5S35 UHnUR U5 M g![ a*n[R"SUSSU35 SnAMISnAff=f) z5Load all enabled jobs from database and schedule themT) enabled_onlyzLoading z enabled jobszError scheduling job 'namez': N)r get_all_jobsr rr2 _schedule_jobr9error)r$jobsjobr;s r%r0SchedulerDaemon._load_jobs~sww###6 hs4yk78C K""3' K 5c&k]#aSIJJ KsA B #BB rLc PSSKnUSnUSnUSnURUS5nURXV5nU(d[R"SUS35 gUR R URUU/S U3US S 9 [R"S US USUS35 g)zN Schedule a job with APScheduler Args: job: Job definition from database rNidrG schedule_typeschedule_configz!Could not build trigger for job 'z ', skippingjob_T)functriggerargsrOrGreplace_existingzScheduled job 'z' (ID z) with z trigger) jsonloads_build_triggerr rAradd_job_execute_scheduled_jobr)r$rLrWjob_idjob_namerPrQrTs r%rISchedulerDaemon._schedule_jobs Tv;O, **S):%;<%%mE NN>xj T U  ,,fX!    ohZvfXW]OS[\]r(rPrQcUS:Xa0URS5nU(a[R"U5$gUS:Xa [S0UD6$US:Xa!URS5nU(a [ US9$g)z Build APScheduler trigger from schedule configuration Args: schedule_type: 'cron', 'interval', or 'date' schedule_config: Configuration dict Returns: APScheduler trigger object cronintervaldaterun_date)rcN)r6r from_crontabrr)r$rPrQ cron_exprrcs r%rYSchedulerDaemon._build_triggers{ F "'++F3I"// ::j ("5_5 5 f $&**:6H"H55r(r\cP[R"SU35 URRUSS9nU(a[R"SUSUS35 g [R"SUS35 g ![ a&n[R "SUS U35 S nAg S nAff=f) zV Execute a scheduled job (called by APScheduler) Args: job_id: Job ID to execute z(Triggered scheduled execution of job ID r triggered_byzJob ID z$ queued for execution (execution ID )z could not be queuedzError executing scheduled job z: N)r rr execute_jobrAr9r:)r$r\ execution_idr;s r%r[&SchedulerDaemon._execute_scheduled_jobs  >vhGH M==44V+4VL gfX-QR^Q__`ab0DEF M   =fXRsK L L Ms>A5A55 B%?B  B%cURR5nUHn[R"US5n[R"5U- R 5nURR US5nU(dMiXESS-:dMv[R"SUSS35 URRUSS[R"5S S 9 M g ) z!Periodic health check and cleanup start_timer\timeout_secondsz Execution rOz! appears stuck, marking as failedfailedz@Execution exceeded 2x timeout - marked as failed by health check)statusend_time error_messageN) rr@r fromisoformatnow total_secondsget_jobr rAupdate_execution)r$rB executionrp running_timerLs r%r7SchedulerDaemon._health_checks..0I!// ,0GHJ$LLNZ7FFHL''//)H"56Cs|+<'='ABIdO+<<]^_((dO#%\\^"d ) r(cURRU5nU(a:US(a/URU5 [R"SUSS35 ggg)zN Add or update a job in the scheduler Args: job_id: Job ID to add/update enabledzAdded/updated job 'rGz' in schedulerN)rrzrIr r)r$r\rLs r%add_job_to_schedule#SchedulerDaemon.add_job_to_schedulesNggoof% 3y>   s # KK-c&k].I J"3r(cURRSU35 [R"SUS35 g![a&n[R "SUSU35 SnAgSnAff=f)zE Remove a job from the scheduler Args: job_id: Job ID to remove rRzRemoved job ID z from schedulerzCould not remove job z from scheduler: N)r remove_jobr rr9rA)r$r\r;s r%remove_job_from_schedule(SchedulerDaemon.remove_job_from_schedulese Q NN % %VHo 6 KK/&A B Q NN26(:KA3O P P Qs8; A+A&&A+returnch[R"SU35 URRUSS9$)zn Execute a job manually (outside of schedule) Args: job_id: Job ID to execute Returns: Execution ID z&Manual execution requested for job ID manualri)r rrrl)r$r\s r%execute_job_manually$SchedulerDaemon.execute_job_manually s2  rs\  A191+'%+I I X& zFr(