@@ -148,9 +148,18 @@ private function processApplicationErrors($config)
148148 foreach ($ errors as $ error ) {
149149 $ this ->processedCount ++;
150150
151- if ($ this ->shouldAnalyzeError ($ error , $ config )) {
151+ $ dedupId = $ this ->shouldAnalyzeError ($ error , $ config );
152+ if ($ dedupId !== false ) {
152153 $ this ->queueErrorForAnalysis ($ error , $ config );
153154 $ this ->queuedCount ++;
155+
156+ // Update last_analyzed timestamp AFTER successful queueing
157+ $ sql = "
158+ UPDATE AIErrorDeduplication
159+ SET last_analyzed = UNIX_TIMESTAMP()
160+ WHERE id = ?
161+ " ;
162+ DBI ::prepared_query ($ sql , 'i ' , [$ dedupId ]);
154163 } else {
155164 $ this ->skippedCount ++;
156165 }
@@ -164,6 +173,8 @@ private function processApplicationErrors($config)
164173
165174 /**
166175 * Check if error should be analyzed based on deduplication and cooldown
176+ *
177+ * @return int|false Deduplication record ID if should analyze, false otherwise
167178 */
168179 private function shouldAnalyzeError ($ error , $ config )
169180 {
@@ -182,14 +193,28 @@ private function shouldAnalyzeError($error, $config)
182193
183194 if (empty ($ dedup )) {
184195 // New error signature - create deduplication record
185- // Extract controller name from file path (e.g., "Controller/UserController.php" -> "UserController")
196+ // Extract controller name using same logic as identifyControllerAndFunction
186197 $ controllerName = '' ;
187198 $ filePath = $ error ['file ' ] ?? '' ;
188- if (preg_match ('/([A-Z][a-zA-Z0-9]+Controller)\.php/ ' , $ filePath , $ matches )) {
199+
200+ // Pattern 1: eval()'d code pattern (typical for Kyte dynamic controllers)
201+ if (preg_match ('/Api\.php\(\d+\)\s*:\s*eval/ ' , $ filePath )) {
202+ // Use the model name from error to find controller
203+ $ modelName = $ error ['model ' ] ?? '' ;
204+ if ($ modelName ) {
205+ $ controllerName = $ modelName . 'Controller ' ;
206+ }
207+ }
208+ // Pattern 2: Direct controller file path
209+ elseif (preg_match ('/([A-Z][a-zA-Z0-9]+Controller)\.php/ ' , $ filePath , $ matches )) {
189210 $ controllerName = $ matches [1 ];
190- } elseif (preg_match ('/\/([^\/]+)\.php$/ ' , $ filePath , $ matches )) {
211+ }
212+ // Pattern 3: Generic PHP file
213+ elseif (preg_match ('/\/([^\/]+)\.php$/ ' , $ filePath , $ matches )) {
191214 $ controllerName = $ matches [1 ];
192- } else {
215+ }
216+
217+ if (!$ controllerName ) {
193218 $ controllerName = 'Unknown ' ;
194219 }
195220
@@ -200,7 +225,7 @@ private function shouldAnalyzeError($error, $config)
200225 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
201226 " ;
202227
203- DBI ::prepared_query ($ sql , 'iisssssii ' , [
228+ $ dedupId = DBI ::prepared_query ($ sql , 'iisssssii ' , [
204229 $ config ['application ' ],
205230 $ config ['kyte_account ' ],
206231 $ signature ,
@@ -212,7 +237,7 @@ private function shouldAnalyzeError($error, $config)
212237 $ error ['date_created ' ]
213238 ]);
214239
215- return true ; // Analyze new error
240+ return $ dedupId ; // Return new dedup record ID
216241 }
217242
218243 $ dedup = $ dedup [0 ];
@@ -244,16 +269,7 @@ private function shouldAnalyzeError($error, $config)
244269 }
245270 }
246271
247- // Update last analyzed timestamp
248- $ sql = "
249- UPDATE AIErrorDeduplication
250- SET last_analyzed = UNIX_TIMESTAMP()
251- WHERE id = ?
252- " ;
253-
254- DBI ::prepared_query ($ sql , 'i ' , [$ dedup ['id ' ]]);
255-
256- return true ; // Analyze (cooldown expired)
272+ return $ dedup ['id ' ]; // Return dedup ID to update after successful queueing
257273 }
258274
259275 /**
0 commit comments