Skip to content

Instantly share code, notes, and snippets.

@stevekrouse
Created February 16, 2025 00:11
Show Gist options
  • Save stevekrouse/ae840767e1a56f2bb1623401feb98d02 to your computer and use it in GitHub Desktop.
Save stevekrouse/ae840767e1a56f2bb1623401feb98d02 to your computer and use it in GitHub Desktop.

Revisions

  1. stevekrouse created this gist Feb 16, 2025.
    91 changes: 91 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,91 @@
    Find the bug

    import { email } from "https://esm.town/v/std/email?v=13";
    const MAX_TRIES = 3;
    export async function uptimeCheck(url: string, attempt = 1) {
    let ok = true;
    try {
    const res = await fetch(url);
    if (res.status === 200) {
    console.log(`Website up (${url})`);
    } else {
    ok = false;
    }
    } catch (e) {
    ok = false;
    }
    if (!ok) {
    if (attempt < MAX_TRIES) {
    console.log(`${url} down, attempt ${attempt}, retrying...`);
    return uptimeCheck(url, attempt + 1);
    } else {
    console.log(`${url} down, attempt ${attempt}, notifying...`);
    await email({ subject: `Website down (${url})` });
    }
    }
    }
    const urls = [
    "https://www.google.com",
    "https://www.youtube.com",
    "https://www.biasdfafng.com",
    ];
    await Promise.all(
    urls.map(uptimeCheck),
    );

    =====================

    There's a bug in how the function handles the return value during recursive retries. Here's the issue and fix:

    The function doesn't return a value in the success case (when `ok` is true), which means it returns `undefined`. In the retry case, while it returns the recursive call to `uptimeCheck`, this value isn't being used or propagated up.

    Here's the corrected version:

    ```typescript
    import { email } from "https://esm.town/v/std/email?v=13";
    const MAX_TRIES = 3;

    export async function uptimeCheck(url: string, attempt = 1) {
    let ok = true;
    try {
    const res = await fetch(url);
    if (res.status === 200) {
    console.log(`Website up (${url})`);
    return true; // Add explicit return for success case
    } else {
    ok = false;
    }
    } catch (e) {
    ok = false;
    }

    if (!ok) {
    if (attempt < MAX_TRIES) {
    console.log(`${url} down, attempt ${attempt}, retrying...`);
    return uptimeCheck(url, attempt + 1);
    } else {
    console.log(`${url} down, attempt ${attempt}, notifying...`);
    await email({ subject: `Website down (${url})` });
    return false; // Add explicit return for failure case
    }
    }
    }

    const urls = [
    "https://www.google.com",
    "https://www.youtube.com",
    "https://www.biasdfafng.com",
    ];

    await Promise.all(
    urls.map(uptimeCheck),
    );
    ```

    The main changes made:
    1. Added `return true` in the success case when status is 200
    2. Added `return false` after sending the email in the failure case

    Without these explicit returns, the function could return `undefined` in some cases, which makes it harder to track the actual status of each check. Now the function will consistently return a boolean indicating whether the check ultimately succeeded or failed.

    This is important because Promise.all() is being used to run these checks in parallel, and having proper return values makes it easier to handle and track the results if needed.