Openstatus www.openstatus.dev

add retry to status update (#1696)

authored by

Thibault Le Ouay and committed by
GitHub
403c245c 02b26ba0

+103 -95
+2 -2
package.json
··· 23 23 "@biomejs/biome": "1.8.3", 24 24 "@turbo/gen": "1.13.3", 25 25 "oxfmt": "0.20.0", 26 - "oxlint": "1.35.0", 27 - "oxlint-tsgolint": "0.10.0", 26 + "oxlint": "1.36.0", 27 + "oxlint-tsgolint": "0.10.1", 28 28 "@types/node": "24.0.8", 29 29 "knip": "5.75.1", 30 30 "turbo": "2.6.3",
+1
packages/emails/package.json
··· 17 17 "@react-email/render": "2.0.0", 18 18 "@react-email/tailwind": "2.0.1", 19 19 "@t3-oss/env-core": "0.13.10", 20 + "effect": "3.19.12", 20 21 "react-email": "5.0.8", 21 22 "resend": "6.6.0", 22 23 "zod": "4.1.13"
+30 -26
packages/emails/src/client.tsx
··· 1 1 /** @jsxImportSource react */ 2 2 3 3 import { render } from "@react-email/render"; 4 + import { Effect, Schedule } from "effect"; 4 5 import { Resend } from "resend"; 5 6 import FollowUpEmail from "../emails/followup"; 6 7 import type { MonitorAlertProps } from "../emails/monitor-alert"; ··· 98 99 return; 99 100 } 100 101 101 - try { 102 - const html = await render(<StatusReportEmail {...req} />); 102 + const html = await render(<StatusReportEmail {...req} />); 103 103 104 - for (const recipients of chunk(req.to, 100)) { 105 - const result = await this.client.batch.send( 106 - recipients.map((subscriber) => ({ 107 - from: `${req.pageTitle} <notifications@notifications.openstatus.dev>`, 108 - subject: req.reportTitle, 109 - to: subscriber, 110 - html, 111 - })), 112 - ); 113 - 114 - if (result.error) { 115 - console.error( 116 - `Error sending status report update batch to ${recipients}: ${result.error}`, 117 - ); 118 - } 119 - } 120 - 121 - console.log( 122 - `Sent status report update email to ${req.to.length} subscribers`, 104 + for (const recipients of chunk(req.to, 100)) { 105 + const sendEmail = Effect.tryPromise({ 106 + try: () => 107 + this.client.batch.send( 108 + recipients.map((subscriber) => ({ 109 + from: `${req.pageTitle} <notifications@notifications.openstatus.dev>`, 110 + subject: req.reportTitle, 111 + to: subscriber, 112 + html, 113 + })), 114 + ), 115 + catch: (_unknown) => 116 + new Error( 117 + `Error sending status report update batch to ${recipients}`, 118 + ), 119 + }).pipe( 120 + Effect.andThen((result) => 121 + result.error ? Effect.fail(result.error) : Effect.succeed(result), 122 + ), 123 + Effect.retry({ 124 + times: 3, 125 + schedule: Schedule.exponential("1000 millis"), 126 + }), 123 127 ); 124 - } catch (err) { 125 - console.error( 126 - `Error sending status report update email to ${req.to}`, 127 - err, 128 - ); 128 + await Effect.runPromise(sendEmail).catch(console.error); 129 129 } 130 + 131 + console.log( 132 + `Sent status report update email to ${req.to.length} subscribers`, 133 + ); 130 134 } 131 135 132 136 public async sendTeamInvitation(req: TeamInvitationProps & { to: string }) {
+70 -67
pnpm-lock.yaml
··· 27 27 specifier: 0.20.0 28 28 version: 0.20.0 29 29 oxlint: 30 - specifier: 1.35.0 31 - version: 1.35.0(oxlint-tsgolint@0.10.0) 30 + specifier: 1.36.0 31 + version: 1.36.0(oxlint-tsgolint@0.10.1) 32 32 oxlint-tsgolint: 33 - specifier: 0.10.0 34 - version: 0.10.0 33 + specifier: 0.10.1 34 + version: 0.10.1 35 35 turbo: 36 36 specifier: 2.6.3 37 37 version: 2.6.3 ··· 1372 1372 '@t3-oss/env-core': 1373 1373 specifier: 0.13.10 1374 1374 version: 0.13.10(typescript@5.9.3)(zod@4.1.13) 1375 + effect: 1376 + specifier: 3.19.12 1377 + version: 3.19.12 1375 1378 react-email: 1376 1379 specifier: 5.0.8 1377 1380 version: 5.0.8 ··· 4036 4039 cpu: [x64] 4037 4040 os: [win32] 4038 4041 4039 - '@oxlint-tsgolint/darwin-arm64@0.10.0': 4040 - resolution: {integrity: sha512-mhBF/pjey0UdLL1ocU46Fqta+uJuRfqrLfDpcViRg17BtDiUNd8JY9iN2FOoS2HGSCAgCUjZ0AZkwkHwFs/VTw==} 4042 + '@oxlint-tsgolint/darwin-arm64@0.10.1': 4043 + resolution: {integrity: sha512-KGC4++BeEqrIcmDHiJt/e6/860PWJmUJjjp0mE+smpBmRXMjmOFFjrPmN+ZyCyVgf1WdmhPkQXsRSPeTR+2omw==} 4041 4044 cpu: [arm64] 4042 4045 os: [darwin] 4043 4046 4044 - '@oxlint-tsgolint/darwin-x64@0.10.0': 4045 - resolution: {integrity: sha512-roLi34mw/i1z+NS7luboix55SXyhVv38dNUTcRDkk+0lNPzI9ngrM+1y1N2oBSUmz5o9OZGnfJJ7BSGCw/fFEQ==} 4047 + '@oxlint-tsgolint/darwin-x64@0.10.1': 4048 + resolution: {integrity: sha512-tvmrDgj3Q0tdc+zMWfCVLVq8EQDEUqasm1zaWgSMYIszpID6qdgqbT+OpWWXV9fLZgtvrkoXGwxkHAUJzdVZXQ==} 4046 4049 cpu: [x64] 4047 4050 os: [darwin] 4048 4051 4049 - '@oxlint-tsgolint/linux-arm64@0.10.0': 4050 - resolution: {integrity: sha512-HL9NThPH1V2F6l9XhwNmhQZUknN4m4yQYEvQFFGfZTYN6cvEEBIiqfF4KvBUg8c0xadMbQlW+Ug7/ybA9Nn+CA==} 4052 + '@oxlint-tsgolint/linux-arm64@0.10.1': 4053 + resolution: {integrity: sha512-7kD28z6/ykGx8WetKTPRZt30pd+ziassxg/8cM24lhjUI+hNXyRHVtHes73dh9D6glJKno+1ut+3amUdZBZcpQ==} 4051 4054 cpu: [arm64] 4052 4055 os: [linux] 4053 4056 4054 - '@oxlint-tsgolint/linux-x64@0.10.0': 4055 - resolution: {integrity: sha512-Tw8QNq8ab+4+qE5krvJyMA66v6XE3GoiISRD5WmJ7YOxUnu//jSw/bBm7OYf/TNEZyeV0BTR7zXzhT5R+VFWlQ==} 4057 + '@oxlint-tsgolint/linux-x64@0.10.1': 4058 + resolution: {integrity: sha512-NmJmiqdzYUTHIxteSTyX6IFFgnIsOAjRWXfrS6Jbo5xlB3g39WHniSF3asB/khLJNtwSg4InUS34NprYM7zrEw==} 4056 4059 cpu: [x64] 4057 4060 os: [linux] 4058 4061 4059 - '@oxlint-tsgolint/win32-arm64@0.10.0': 4060 - resolution: {integrity: sha512-LTogmTRwpwQqVaH1Ama8Wd5/VVZWBSF8v5qTbeT628+1F5Kt1V5eHBvyFh4oN18UCZlgqrh7DqkDhsieXUaC8Q==} 4062 + '@oxlint-tsgolint/win32-arm64@0.10.1': 4063 + resolution: {integrity: sha512-3KrT80vl3nXUkjuJI/z8dF6xWsKx0t9Tz4ZQHgQw3fYw+CoihBRWGklrdlmCz+EGfMyVaQLqBV9PZckhSqLe2A==} 4061 4064 cpu: [arm64] 4062 4065 os: [win32] 4063 4066 4064 - '@oxlint-tsgolint/win32-x64@0.10.0': 4065 - resolution: {integrity: sha512-ygqxx8EmNWy9/wCQS5uXq9k/o2EyYNwNxY1ZHNzlmZC/kV06Aemx5OBDafefawBNqH7xTZPfccUrjdiy+QlTrw==} 4067 + '@oxlint-tsgolint/win32-x64@0.10.1': 4068 + resolution: {integrity: sha512-hW1fSJZVxG51sLdGq1sQjOzb1tsQ23z/BquJfUwL7CqBobxr7TJvGmoINL+9KryOJt0jCoaiMfWe4yoYw5XfIA==} 4066 4069 cpu: [x64] 4067 4070 os: [win32] 4068 4071 4069 - '@oxlint/darwin-arm64@1.35.0': 4070 - resolution: {integrity: sha512-ieiYVHkNZPo77Hgrxav595wGS4rRNKuDNrljf+4xhwpJsddrxMpM64IQUf2IvR3MhK4FxdGzhhB6OVmGVHY5/w==} 4072 + '@oxlint/darwin-arm64@1.36.0': 4073 + resolution: {integrity: sha512-MJkj82GH+nhvWKJhSIM6KlZ8tyGKdogSQXtNdpIyP02r/tTayFJQaAEWayG2Jhsn93kske+nimg5MYFhwO/rlg==} 4071 4074 cpu: [arm64] 4072 4075 os: [darwin] 4073 4076 4074 - '@oxlint/darwin-x64@1.35.0': 4075 - resolution: {integrity: sha512-1jNHu3j66X5jKySvgtE+jGtjx4ye+xioAucVTi2IuROZO6keK2YG74pnD+9FT+DpWZAtWRZGoW0r0x6aN9sEEg==} 4077 + '@oxlint/darwin-x64@1.36.0': 4078 + resolution: {integrity: sha512-VvEhfkqj/99dCTqOcfkyFXOSbx4lIy5u2m2GHbK4WCMDySokOcMTNRHGw8fH/WgQ5cDrDMSTYIGQTmnBGi9tiQ==} 4076 4079 cpu: [x64] 4077 4080 os: [darwin] 4078 4081 4079 - '@oxlint/linux-arm64-gnu@1.35.0': 4080 - resolution: {integrity: sha512-T1lc0UaYbTxZyqVpLfC7eipbauNG8pBpkaZEW4JGz8Y68rxTH7d9s+CF0zxUxNr5RCtcmT669RLVjQT7VrKVLg==} 4082 + '@oxlint/linux-arm64-gnu@1.36.0': 4083 + resolution: {integrity: sha512-EMx92X5q+hHc3olTuj/kgkx9+yP0p/AVs4yvHbUfzZhBekXNpUWxWvg4hIKmQWn+Ee2j4o80/0ACGO0hDYJ9mg==} 4081 4084 cpu: [arm64] 4082 4085 os: [linux] 4083 4086 4084 - '@oxlint/linux-arm64-musl@1.35.0': 4085 - resolution: {integrity: sha512-7Wv5Pke9kwWKFycUziSHsmi3EM0389TLzraB0KE/MArrKxx30ycwfJ5PYoMj9ERoW+Ybs0txdaOF/xJy/XyYkg==} 4087 + '@oxlint/linux-arm64-musl@1.36.0': 4088 + resolution: {integrity: sha512-7YCxtrPIctVYLqWrWkk8pahdCxch6PtsaucfMLC7TOlDt4nODhnQd4yzEscKqJ8Gjrw1bF4g+Ngob1gB+Qr9Fw==} 4086 4089 cpu: [arm64] 4087 4090 os: [linux] 4088 4091 4089 - '@oxlint/linux-x64-gnu@1.35.0': 4090 - resolution: {integrity: sha512-HDMPOzyVVy+rQl3H7UOq8oGHt7m1yaiWCanlhAu4jciK8dvXeO9OG/OQd74lD/h05IcJh93pCLEJ3wWOG8hTiQ==} 4092 + '@oxlint/linux-x64-gnu@1.36.0': 4093 + resolution: {integrity: sha512-lnaJVlx5r3NWmoOMesfQXJSf78jHTn8Z+sdAf795Kgteo72+qGC1Uax2SToCJVN2J8PNG3oRV5bLriiCNR2i6Q==} 4091 4094 cpu: [x64] 4092 4095 os: [linux] 4093 4096 4094 - '@oxlint/linux-x64-musl@1.35.0': 4095 - resolution: {integrity: sha512-kAPBBsUOM3HQQ6n3nnZauvFR9EoXqCSoj4O3OSXXarzsRTiItNrHabVUwxeswZEc+xMzQNR0FHEWg/d4QAAWLw==} 4097 + '@oxlint/linux-x64-musl@1.36.0': 4098 + resolution: {integrity: sha512-AhuEU2Qdl66lSfTGu/Htirq8r/8q2YnZoG3yEXLMQWnPMn7efy8spD/N1NA7kH0Hll+cdfwgQkQqC2G4MS2lPQ==} 4096 4099 cpu: [x64] 4097 4100 os: [linux] 4098 4101 4099 - '@oxlint/win32-arm64@1.35.0': 4100 - resolution: {integrity: sha512-qrpBkkOASS0WT8ra9xmBRXOEliN6D/MV9JhI/68lFHrtLhfFuRwg4AjzjxrCWrQCnQ0WkvAVpJzu73F4ICLYZw==} 4102 + '@oxlint/win32-arm64@1.36.0': 4103 + resolution: {integrity: sha512-GlWCBjUJY2QgvBFuNRkiRJu7K/djLmM0UQKfZV8IN+UXbP/JbjZHWKRdd4LXlQmzoz7M5Hd6p+ElCej8/90FCg==} 4101 4104 cpu: [arm64] 4102 4105 os: [win32] 4103 4106 4104 - '@oxlint/win32-x64@1.35.0': 4105 - resolution: {integrity: sha512-yPFcj6umrhusnG/kMS5wh96vblsqZ0kArQJS+7kEOSJDrH+DsFWaDCsSRF8U6gmSmZJ26KVMU3C3TMpqDN4M1g==} 4107 + '@oxlint/win32-x64@1.36.0': 4108 + resolution: {integrity: sha512-J+Vc00Utcf8p77lZPruQgb0QnQXuKnFogN88kCnOqs2a83I+vTBB8ILr0+L9sTwVRvIDMSC0pLdeQH4svWGFZg==} 4106 4109 cpu: [x64] 4107 4110 os: [win32] 4108 4111 ··· 9350 9353 engines: {node: ^20.19.0 || >=22.12.0} 9351 9354 hasBin: true 9352 9355 9353 - oxlint-tsgolint@0.10.0: 9354 - resolution: {integrity: sha512-LDDSIu5J/4D4gFUuQQIEQpAC6maNEbMg4nC8JL/+Pe0cUDR86dtVZ09E2x5MwCh8f9yfktoaxt5x6UIVyzrajg==} 9356 + oxlint-tsgolint@0.10.1: 9357 + resolution: {integrity: sha512-EEHNdo5cW2w1xwYdBQ7d3IXDqWAtMkfVFrh+9gQ4kYbYJwygY4QXSh1eH80/xVipZdVKujAwBgg/nNNHk56kxQ==} 9355 9358 hasBin: true 9356 9359 9357 - oxlint@1.35.0: 9358 - resolution: {integrity: sha512-QDX1aUgaiqznkGfTM2qHwva2wtKqhVoqPSVXrnPz+yLUhlNadikD3QRuRtppHl7WGuy3wG6nKAuR8lash3aWSg==} 9360 + oxlint@1.36.0: 9361 + resolution: {integrity: sha512-IicUdXfXgI8OKrDPnoSjvBfeEF8PkKtm+CoLlg4LYe4ypc8U+T4r7730XYshdBGZdelg+JRw8GtCb2w/KaaZvw==} 9359 9362 engines: {node: ^20.19.0 || >=22.12.0} 9360 9363 hasBin: true 9361 9364 peerDependencies: ··· 13640 13643 '@oxfmt/win32-x64@0.20.0': 13641 13644 optional: true 13642 13645 13643 - '@oxlint-tsgolint/darwin-arm64@0.10.0': 13646 + '@oxlint-tsgolint/darwin-arm64@0.10.1': 13644 13647 optional: true 13645 13648 13646 - '@oxlint-tsgolint/darwin-x64@0.10.0': 13649 + '@oxlint-tsgolint/darwin-x64@0.10.1': 13647 13650 optional: true 13648 13651 13649 - '@oxlint-tsgolint/linux-arm64@0.10.0': 13652 + '@oxlint-tsgolint/linux-arm64@0.10.1': 13650 13653 optional: true 13651 13654 13652 - '@oxlint-tsgolint/linux-x64@0.10.0': 13655 + '@oxlint-tsgolint/linux-x64@0.10.1': 13653 13656 optional: true 13654 13657 13655 - '@oxlint-tsgolint/win32-arm64@0.10.0': 13658 + '@oxlint-tsgolint/win32-arm64@0.10.1': 13656 13659 optional: true 13657 13660 13658 - '@oxlint-tsgolint/win32-x64@0.10.0': 13661 + '@oxlint-tsgolint/win32-x64@0.10.1': 13659 13662 optional: true 13660 13663 13661 - '@oxlint/darwin-arm64@1.35.0': 13664 + '@oxlint/darwin-arm64@1.36.0': 13662 13665 optional: true 13663 13666 13664 - '@oxlint/darwin-x64@1.35.0': 13667 + '@oxlint/darwin-x64@1.36.0': 13665 13668 optional: true 13666 13669 13667 - '@oxlint/linux-arm64-gnu@1.35.0': 13670 + '@oxlint/linux-arm64-gnu@1.36.0': 13668 13671 optional: true 13669 13672 13670 - '@oxlint/linux-arm64-musl@1.35.0': 13673 + '@oxlint/linux-arm64-musl@1.36.0': 13671 13674 optional: true 13672 13675 13673 - '@oxlint/linux-x64-gnu@1.35.0': 13676 + '@oxlint/linux-x64-gnu@1.36.0': 13674 13677 optional: true 13675 13678 13676 - '@oxlint/linux-x64-musl@1.35.0': 13679 + '@oxlint/linux-x64-musl@1.36.0': 13677 13680 optional: true 13678 13681 13679 - '@oxlint/win32-arm64@1.35.0': 13682 + '@oxlint/win32-arm64@1.36.0': 13680 13683 optional: true 13681 13684 13682 - '@oxlint/win32-x64@1.35.0': 13685 + '@oxlint/win32-x64@1.36.0': 13683 13686 optional: true 13684 13687 13685 13688 '@pagefind/darwin-arm64@1.4.0': ··· 19669 19672 '@oxfmt/win32-arm64': 0.20.0 19670 19673 '@oxfmt/win32-x64': 0.20.0 19671 19674 19672 - oxlint-tsgolint@0.10.0: 19675 + oxlint-tsgolint@0.10.1: 19673 19676 optionalDependencies: 19674 - '@oxlint-tsgolint/darwin-arm64': 0.10.0 19675 - '@oxlint-tsgolint/darwin-x64': 0.10.0 19676 - '@oxlint-tsgolint/linux-arm64': 0.10.0 19677 - '@oxlint-tsgolint/linux-x64': 0.10.0 19678 - '@oxlint-tsgolint/win32-arm64': 0.10.0 19679 - '@oxlint-tsgolint/win32-x64': 0.10.0 19677 + '@oxlint-tsgolint/darwin-arm64': 0.10.1 19678 + '@oxlint-tsgolint/darwin-x64': 0.10.1 19679 + '@oxlint-tsgolint/linux-arm64': 0.10.1 19680 + '@oxlint-tsgolint/linux-x64': 0.10.1 19681 + '@oxlint-tsgolint/win32-arm64': 0.10.1 19682 + '@oxlint-tsgolint/win32-x64': 0.10.1 19680 19683 19681 - oxlint@1.35.0(oxlint-tsgolint@0.10.0): 19684 + oxlint@1.36.0(oxlint-tsgolint@0.10.1): 19682 19685 optionalDependencies: 19683 - '@oxlint/darwin-arm64': 1.35.0 19684 - '@oxlint/darwin-x64': 1.35.0 19685 - '@oxlint/linux-arm64-gnu': 1.35.0 19686 - '@oxlint/linux-arm64-musl': 1.35.0 19687 - '@oxlint/linux-x64-gnu': 1.35.0 19688 - '@oxlint/linux-x64-musl': 1.35.0 19689 - '@oxlint/win32-arm64': 1.35.0 19690 - '@oxlint/win32-x64': 1.35.0 19691 - oxlint-tsgolint: 0.10.0 19686 + '@oxlint/darwin-arm64': 1.36.0 19687 + '@oxlint/darwin-x64': 1.36.0 19688 + '@oxlint/linux-arm64-gnu': 1.36.0 19689 + '@oxlint/linux-arm64-musl': 1.36.0 19690 + '@oxlint/linux-x64-gnu': 1.36.0 19691 + '@oxlint/linux-x64-musl': 1.36.0 19692 + '@oxlint/win32-arm64': 1.36.0 19693 + '@oxlint/win32-x64': 1.36.0 19694 + oxlint-tsgolint: 0.10.1 19692 19695 19693 19696 p-limit@3.1.0: 19694 19697 dependencies: