(args, label, options = {})
| 795 | } |
| 796 | |
| 797 | async function retrySimdeckText(args, label, options = {}) { |
| 798 | const attempts = options.attempts ?? 6; |
| 799 | const delayMs = options.delayMs ?? 2_000; |
| 800 | const healthTimeoutMs = options.healthTimeoutMs ?? 60_000; |
| 801 | let lastError; |
| 802 | for (let attempt = 1; attempt <= attempts; attempt += 1) { |
| 803 | try { |
| 804 | return simdeckText(args, options); |
| 805 | } catch (error) { |
| 806 | lastError = error; |
| 807 | if (attempt === attempts) { |
| 808 | break; |
| 809 | } |
| 810 | if (isServiceConnectionError(error)) { |
| 811 | logStep( |
| 812 | `${label} lost service connection on attempt ${attempt}; waiting for health before retry`, |
| 813 | ); |
| 814 | try { |
| 815 | await waitForHealth({ timeoutMs: healthTimeoutMs }); |
| 816 | } catch (healthError) { |
| 817 | lastError = healthError; |
| 818 | } |
| 819 | } |
| 820 | await sleep(delayMs); |
| 821 | } |
| 822 | } |
| 823 | throw new Error( |
| 824 | `${label} failed after ${attempts} attempts: ${lastError?.message ?? lastError}`, |
| 825 | ); |
| 826 | } |
| 827 | |
| 828 | function isServiceConnectionError(error) { |
| 829 | const message = String(error?.message ?? error).toLowerCase(); |
no test coverage detected