Add retry mechanism and failure notifications for nCore/qBittorrent setup
- Implemented a retry mechanism for external calls, allowing up to 3 attempts before failing. - Enhanced error handling to send failure notifications when setup steps fail, including detailed error messages. - Updated RunSummary model to include status, error step, and error message fields for better tracking of run outcomes. - Modified database schema to store failure metadata for runs. - Updated README.md to reflect changes in error handling and notification behavior.
This commit is contained in:
@@ -135,10 +135,17 @@ func (s *Store) MarkManualNeeded(id int64, now time.Time) error {
|
||||
}
|
||||
|
||||
func (s *Store) InsertRun(summary model.RunSummary) error {
|
||||
status := summary.Status
|
||||
if status == "" {
|
||||
status = "success"
|
||||
}
|
||||
_, err := s.db.Exec(`
|
||||
INSERT INTO runs (started_at, dry_run, total_risk, matched, unmatched, force_started, reannounced, manual_needed)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, summary.StartedAt.Format(time.RFC3339), boolInt(summary.DryRun), summary.TotalRisk, summary.Matched, summary.Unmatched, summary.ForceStarted, summary.Reannounced, summary.ManualNeeded)
|
||||
INSERT INTO runs (
|
||||
started_at, status, error_step, error_message, dry_run,
|
||||
total_risk, matched, unmatched, force_started, reannounced, manual_needed
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, summary.StartedAt.Format(time.RFC3339), status, summary.ErrorStep, summary.ErrorMessage, boolInt(summary.DryRun), summary.TotalRisk, summary.Matched, summary.Unmatched, summary.ForceStarted, summary.Reannounced, summary.ManualNeeded)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -215,11 +222,22 @@ func (s *Store) lastRun() (*model.RunRecord, error) {
|
||||
var run model.RunRecord
|
||||
var dryRun int
|
||||
err := s.db.QueryRow(`
|
||||
SELECT started_at, dry_run, total_risk, matched, unmatched, force_started, reannounced, manual_needed
|
||||
SELECT
|
||||
started_at,
|
||||
status,
|
||||
COALESCE(error_step, ''),
|
||||
COALESCE(error_message, ''),
|
||||
dry_run,
|
||||
total_risk,
|
||||
matched,
|
||||
unmatched,
|
||||
force_started,
|
||||
reannounced,
|
||||
manual_needed
|
||||
FROM runs
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
`).Scan(&run.StartedAt, &dryRun, &run.TotalRisk, &run.Matched, &run.Unmatched, &run.ForceStarted, &run.Reannounced, &run.ManualNeeded)
|
||||
`).Scan(&run.StartedAt, &run.Status, &run.ErrorStep, &run.ErrorMessage, &dryRun, &run.TotalRisk, &run.Matched, &run.Unmatched, &run.ForceStarted, &run.Reannounced, &run.ManualNeeded)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -327,6 +345,9 @@ func (s *Store) migrate() error {
|
||||
CREATE TABLE IF NOT EXISTS runs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
started_at TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'success',
|
||||
error_step TEXT,
|
||||
error_message TEXT,
|
||||
dry_run INTEGER NOT NULL,
|
||||
total_risk INTEGER NOT NULL,
|
||||
matched INTEGER NOT NULL,
|
||||
@@ -336,6 +357,47 @@ func (s *Store) migrate() error {
|
||||
manual_needed INTEGER NOT NULL
|
||||
);
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.addColumnIfMissing("runs", "status", "TEXT NOT NULL DEFAULT 'success'"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.addColumnIfMissing("runs", "error_step", "TEXT"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.addColumnIfMissing("runs", "error_message", "TEXT"); err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Store) addColumnIfMissing(table string, column string, definition string) error {
|
||||
rows, err := s.db.Query(fmt.Sprintf(`PRAGMA table_info(%s)`, table))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var cid int
|
||||
var name string
|
||||
var columnType string
|
||||
var notNull int
|
||||
var defaultValue sql.NullString
|
||||
var pk int
|
||||
if err := rows.Scan(&cid, &name, &columnType, ¬Null, &defaultValue, &pk); err != nil {
|
||||
return err
|
||||
}
|
||||
if name == column {
|
||||
return rows.Err()
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = s.db.Exec(fmt.Sprintf(`ALTER TABLE %s ADD COLUMN %s %s`, table, column, definition))
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user