1+ <?php
2+
3+ namespace Codepeak \Cronwatch \Cron ;
4+
5+ use \Codepeak \Cronwatch \Model \CronwatchRepository ;
6+ use \Magento \Framework \App \Config \ScopeConfigInterface ;
7+ use \Magento \Framework \ObjectManagerInterface ;
8+ use \Psr \Log \LoggerInterface ;
9+
10+ /**
11+ * Class Monitor
12+ *
13+ * @package Codepeak\Cronwatch\Cron
14+ * @author Robert Lord, Codepeak AB <robert@codepeak.se>
15+ */
16+ class Monitor
17+ {
18+ /**
19+ * @var LoggerInterface
20+ */
21+ protected $ logger ;
22+
23+ /**
24+ * @var ObjectManager
25+ */
26+ protected $ objectManager ;
27+
28+ /**
29+ * @var ScopeConfigInterface
30+ */
31+ protected $ scopeConfig ;
32+
33+ /**
34+ * Constructor
35+ *
36+ * @param LoggerInterface $logger
37+ * @param ObjectManagerInterface $objectManager
38+ * @param ScopeConfigInterface $scopeConfig
39+ */
40+ public function __construct (
41+ LoggerInterface $ logger ,
42+ ObjectManagerInterface $ objectManager ,
43+ ScopeConfigInterface $ scopeConfig
44+ ) {
45+ $ this ->logger = $ logger ;
46+ $ this ->objectManager = $ objectManager ;
47+ $ this ->scopeConfig = $ scopeConfig ;
48+ }
49+
50+ /**
51+ * Execute the cron
52+ *
53+ * @return void
54+ */
55+ public function execute ()
56+ {
57+ // Make sure we're active
58+ if ($ this ->scopeConfig ->getValue ('system/cronwatch/enabled ' ) !== '1 ' ) {
59+ return ;
60+ }
61+
62+ // Build e-mail recipients
63+ $ emailRecipients = [];
64+ foreach (explode (', ' , $ this ->scopeConfig ->getValue ('system/cronwatch/recipients ' )) as $ recipient ) {
65+ $ emailRecipients [] = trim ($ recipient );
66+ }
67+
68+ /**
69+ * Fetch all entries in cron_schedule table
70+ */
71+ $ cronScheduleCollection = $ this ->objectManager ->get ('Magento\Cron\Model\Schedule ' )
72+ ->getCollection ()
73+ ->addFieldToFilter ('status ' , ['eq ' => 'error ' ])
74+ ->addFieldToFilter ('cronwatch_id ' , ['null ' => true ]);
75+
76+ // Left join with our status table
77+ $ cronScheduleCollection
78+ ->getSelect ()
79+ ->joinLeft (
80+ ['cronwatch ' => $ cronScheduleCollection ->getTable ('codepeak_cronwatch ' )],
81+ 'main_table.schedule_id = cronwatch.cron_schedule_schedule_id ' ,
82+ ['cronwatch_id ' ]
83+ );
84+
85+ /**
86+ * Loop each entry and build error string
87+ */
88+ foreach ($ cronScheduleCollection as $ schedule ) {
89+ // Remove data not needed
90+ $ schedule ->unsetData ('cronwatch_id ' );
91+
92+ // Build the message
93+ $ message = "Job with code '%s' marked as failed with the reason '%s'. \n\n%s " ;
94+ $ message = sprintf (
95+ $ message ,
96+ $ schedule ->getJobCode (),
97+ $ schedule ->getMessages (),
98+ var_export ($ schedule ->getData (), true )
99+ );
100+
101+ // Add entry to the logs, might be good to have information here as well
102+ $ this ->logger ->addError ($ message );
103+
104+ // Setup the e-mail
105+ if (count ($ emailRecipients )) {
106+ try {
107+ $ email = new \Zend_Mail ();
108+ $ email ->setSubject ('Cronwatch error detected: ' . $ schedule ->getJobCode ());
109+ $ email ->setBodyText ($ message );
110+ $ email ->setFrom (
111+ $ this ->scopeConfig ->getValue ('trans_email/ident_general/email ' ),
112+ $ this ->scopeConfig ->getValue ('trans_email/ident_general/name ' )
113+ );
114+ $ email ->addTo ($ emailRecipients );
115+ $ email ->send ();
116+ } catch (\Exception $ e ) {
117+ $ this ->logger ->addError ($ e ->getMessage ());
118+ }
119+ }
120+
121+ // Fetch cronwatch repository
122+ $ cronwatchRepository = $ this ->objectManager ->create (CronwatchRepository::class);
123+
124+ // Create entry in our monitor table to avoid duplicates
125+ $ cronwatchModel = $ this ->objectManager ->get ('Codepeak\Cronwatch\Model\Cronwatch ' );
126+ $ cronwatchModel ->setCronScheduleScheduleId ($ schedule ->getScheduleId ());
127+
128+ // Store the entity
129+ $ cronwatchRepository ->save ($ cronwatchModel );
130+ }
131+
132+ // Clean our table in case of table cron_schedule was truncated
133+ $ cronwatchCollection = $ this ->objectManager ->get ('Codepeak\Cronwatch\Model\Cronwatch ' )
134+ ->getCollection ();
135+
136+ // Left join with cron_schedule table
137+ $ cronwatchCollection
138+ ->getSelect ()
139+ ->joinLeft (
140+ ['cron_schedule ' => $ cronwatchCollection ->getTable ('cron_schedule ' )],
141+ 'main_table.cron_schedule_schedule_id = cron_schedule.schedule_id ' ,
142+ ['schedule_id ' ]
143+ );
144+
145+ // Remove entries that no longer exists in cron_schedule table, not 100% fool proof but good enough
146+ foreach ($ cronwatchCollection as $ cronwatch ) {
147+ if (!$ cronwatch ->getScheduleId ()) {
148+ // Fetch cronwatch repository
149+ $ cronwatchRepository = $ this ->objectManager ->create (CronwatchRepository::class);
150+
151+ // Load the model
152+ $ cronwatchModel = $ this ->objectManager ->get ('Codepeak\Cronwatch\Model\Cronwatch ' )->load (
153+ $ cronwatch ->getCronwatchId ()
154+ );
155+
156+ // Delete it
157+ $ cronwatchRepository ->delete ($ cronwatchModel );
158+ }
159+ }
160+ }
161+ }
0 commit comments