also looking at this
fix(dashboard): fail closed when the dashboard lookup errors
#1452
2 files
+39
-4
| @@ -3685,8 +3685,21 @@ export class Buddy { | ||
| 3685 | 3685 | return null |
| 3686 | 3686 | } |
| 3687 | 3687 | catch (error) { |
| 3688 | this.logger.warn(`Failed to search for existing dashboard: ${error}`) | |
| 3689 | return null | |
| 3688 | // "Found nothing" and "the lookup failed" must not collapse to the same | |
| 3689 | // value. The caller treats null as "no dashboard exists" and creates one, | |
| 3690 | // so a transient 5xx, timeout or secondary rate-limit on getIssues() would | |
| 3691 | // open a duplicate dashboard and still exit 0 - permanent damage from a | |
| 3692 | // momentary failure. | |
| 3693 | // | |
| 3694 | // Both call sites reach this: the initial lookup and the pre-create race | |
| 3695 | // check. The race check in particular was no protection at all while it | |
| 3696 | // failed open, because whatever broke the first lookup is usually still | |
| 3697 | // broken a moment later. | |
| 3698 | // | |
| 3699 | // A failed run is recoverable - the next scheduled run retries. A duplicate | |
| 3700 | // dashboard is not: someone has to notice it and close it by hand. | |
| 3701 | this.logger.error(`Failed to search for existing dashboard: ${error}`) | |
| 3702 | throw error | |
| 3690 | 3703 | } |
| 3691 | 3704 | } |
| 3692 | 3705 | } |