stackConsult commited on
Commit
c51b9c7
·
verified ·
1 Parent(s): 0f64dc1

Add comprehensive error handling and state management to cadence_agent.py

Browse files
Files changed (1) hide show
  1. cadence_agent.py +69 -1
cadence_agent.py CHANGED
@@ -253,4 +253,72 @@ class CadenceAgent:
253
 
254
  # TODO: Load from actual data sources
255
  logger.info("Suppression lists loaded")
256
- return suppression_lists
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
  # TODO: Load from actual data sources
255
  logger.info("Suppression lists loaded")
256
+ return suppression_lists
257
+
258
+ def _load_cadence_states(self) -> None:
259
+ """
260
+ Load persisted cadence states from disk.
261
+
262
+ Error handling:
263
+ - FileNotFoundError: Log and continue (first run)
264
+ - JSONDecodeError: Log error, backup corrupt file, continue
265
+ - Exception: Log error and continue with empty state
266
+ """
267
+ try:
268
+ if self.state_file.exists():
269
+ with open(self.state_file, 'r') as f:
270
+ states_data = json.load(f)
271
+ # Reconstruct CadenceState objects
272
+ for lead_id, state_dict in states_data.items():
273
+ # Convert string dates back to datetime objects
274
+ state_dict['start_date'] = datetime.fromisoformat(
275
+ state_dict['start_date']
276
+ )
277
+ if state_dict.get('last_touchpoint_date'):
278
+ state_dict['last_touchpoint_date'] = datetime.fromisoformat(
279
+ state_dict['last_touchpoint_date']
280
+ )
281
+ if state_dict.get('next_touchpoint_date'):
282
+ state_dict['next_touchpoint_date'] = datetime.fromisoformat(
283
+ state_dict['next_touchpoint_date']
284
+ )
285
+ # Reconstruct EngagementLevel enum
286
+ state_dict['engagement_level'] = EngagementLevel(
287
+ state_dict['engagement_level']
288
+ )
289
+ self.cadence_states[lead_id] = CadenceState(**state_dict)
290
+ logger.info(f"Loaded {len(self.cadence_states)} cadence states")
291
+ except FileNotFoundError:
292
+ logger.info("No existing cadence states found (first run)")
293
+ except json.JSONDecodeError as e:
294
+ logger.error(f"Corrupt state file detected: {str(e)}")
295
+ # Backup corrupt file
296
+ backup_file = self.state_file.with_suffix('.json.corrupt')
297
+ self.state_file.rename(backup_file)
298
+ logger.info(f"Backed up corrupt state file to {backup_file}")
299
+ except Exception as e:
300
+ logger.error(f"Unexpected error loading states: {str(e)}")
301
+
302
+ def _initialize_activity_log(self) -> None:
303
+ """
304
+ Initialize activity log CSV file.
305
+
306
+ Error handling:
307
+ - PermissionError: Log error and raise (critical)
308
+ - OSError: Log error and raise (critical)
309
+ """
310
+ try:
311
+ if not self.activity_log.exists():
312
+ with open(self.activity_log, 'w', newline='') as f:
313
+ writer = csv.writer(f)
314
+ writer.writerow([
315
+ 'timestamp', 'lead_id', 'step', 'channel', 'template',
316
+ 'status', 'engagement_level', 'error_message'
317
+ ])
318
+ logger.info(f"Activity log initialized at {self.activity_log}")
319
+ except (PermissionError, OSError) as e:
320
+ logger.error(f"Failed to initialize activity log: {str(e)}")
321
+ raise
322
+ except Exception as e:
323
+ logger.error(f"Unexpected error initializing activity log: {str(e)}")
324
+ raise