Skip to content

fix(core): Centralize server error handling and secure startup#1100

Open
Aathish101 wants to merge 1 commit intodigitomize:mainfrom
Aathish101:patch-3
Open

fix(core): Centralize server error handling and secure startup#1100
Aathish101 wants to merge 1 commit intodigitomize:mainfrom
Aathish101:patch-3

Conversation

@Aathish101
Copy link

@Aathish101 Aathish101 commented Oct 9, 2025

…d error logging

Pull Request Details

Description

[Provide a brief overview of the changes introduced by this pull request.]

Fixes

[Cite any related issues or bugs that this PR addresses, e.g., "Fixes #issueNumber"]

Type of PR

  • Bug fix
  • Feature enhancement
  • Documentation update
  • Refactoring
  • Other (specify): _______________

Summary

[Summarize the changes made in this PR.]

Screenshots (if applicable)

[If your changes include UI updates, provide screenshots to illustrate the changes.]

Additional Notes

[Include any additional information or context that might be helpful for reviewers.]

Checklist

  • I have read and followed the Pull Requests and Issues guidelines.
  • The code has been properly linted and formatted using npm run lint:fix and npm run format:fix.
  • I have tested the changes thoroughly before submitting this pull request.
  • I have provided relevant issue numbers, snapshots, and videos after making the changes.
  • I have not borrowed code without disclosing it, if applicable.
  • This pull request is not a Work In Progress (WIP), and only completed and tested changes are included.
  • I have tested these changes locally.
  • My code follows the project's style guidelines.
  • I have updated the documentation accordingly.
  • This PR has a corresponding issue in the issue tracker.

Summary by CodeRabbit

  • Reliability Improvements

    • Enhanced server stability with resilient startup, crash safeguards, and graceful error handling.
    • More consistent background syncs and periodic checks for users, contests, community, extensions, and hackathons.
  • Performance

    • Optimized environment-specific initialization for smoother production behavior.
  • Monitoring

    • Expanded error logging for quicker issue diagnosis and recovery.
  • Chores

    • Consolidated backend server setup and lifecycle management to reduce downtime and improve maintainability.

@netlify
Copy link

netlify bot commented Oct 9, 2025

👷 Deploy request for digitomize pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 9fdab16

@netlify
Copy link

netlify bot commented Oct 9, 2025

👷 Deploy request for v2-digitomize pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 9fdab16

@Aathish101
Copy link
Author

updates

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 9, 2025

Walkthrough

Introduces a new Express server bootstrap at backend/chore/index.js with environment-driven initialization, MongoDB connection, route registration, periodic tasks, and centralized error handling. Removes the legacy server bootstrap at backend/index.js, including its routes, background syncers, and startup logic.

Changes

Cohort / File(s) Summary
New server bootstrap
backend/chore/index.js
Adds modular Express initialization with env-based startup, MongoDB connect, CORS/body parsing, route registration for users/contests/extensions/community/hackathons, periodic sync tasks, 404 handler, centralized error middleware, and process-level error resilience.
Legacy bootstrap removal
backend/index.js
Removes previous Express server setup, route wiring, Firebase admin init, background sync loops, global error handling, and CLI/dev startup logic.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Env as Environment
  participant App as Server Bootstrap
  participant DB as MongoDB
  participant Routes as Routes (Users/Contests/Extensions/Community/Hackathons)
  participant Sched as Periodic Tasks
  participant HTTP as HTTP Server
  participant Err as Error Middleware

  Env->>App: Read config (NODE_ENV, PORT, flags)
  App->>DB: Connect
  DB-->>App: Connected / Error
  App->>Routes: Register routes
  App->>Sched: Start syncers/validators/heartbeats
  App->>HTTP: Listen(PORT)
  HTTP-->>Env: Startup log/ready

  note over App,HTTP: Production vs Development startup branches

  alt Request handled
    HTTP->>Routes: Incoming request
    Routes-->>HTTP: Response
  else Not Found
    HTTP->>Err: 404 handler
    Err-->>HTTP: 404 response
  else Route Error
    Routes-->>Err: Throw/next(err)
    Err-->>HTTP: Error response
  end

  par Process-level resilience
    App-)App: Handle uncaughtException
    App-)App: Handle unhandledRejection
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I nibbled wires, then hopped anew,
A sturdier server now comes through.
Old burrow closed, logs hum along,
Heartbeats thump a steady song.
If errors pounce, I twitch—recover!
In fields of routes, I scamper over.
Carrots deployed; uptime cover. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description consists solely of the unfilled template sections and a fragmentary commit summary, lacking any actual overview, issue references, PR type, detailed summary, or checklist confirmations. As a result, it fails to convey the specific purpose or scope of the changes and omits all required information from the repository’s description template. Please complete each section of the provided template by adding a clear description of the changes, citing any related issues under “Fixes,” selecting the appropriate PR type, summarizing the modifications made, and updating or removing the checklist items to reflect completed validations.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “fix(core): Centralize server error handling and secure startup” succinctly and accurately describes the primary change of consolidating error handling logic and enhancing startup security, matching the refactored server bootstrap and logging improvements in the diff. It is clear, specific, and focuses on the main intent without extraneous detail.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7797ed and 9fdab16.

📒 Files selected for processing (2)
  • backend/chore: Update index.js for stability and error logging (1 hunks)
  • backend/index.js (0 hunks)
💤 Files with no reviewable changes (1)
  • backend/index.js

Comment on lines +55 to +63
console.log(process.env.TEST);
async function main() {
  try {
    console.log("Pinging...");
    await fetchContestsData();
    console.log("Pong!");
  } catch (error) {
    console.error("Error pinging the server:", error);
  }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove the environment-variable debug log.

Logging process.env.TEST in production dumps environment content to stdout, which can leak secrets in aggregated logs. Please drop this statement.

-console.log(process.env.TEST);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log(process.env.TEST);
async function main() {
  try {
    console.log("Pinging...");
    await fetchContestsData();
    console.log("Pong!");
  } catch (error) {
    console.error("Error pinging the server:", error);
  }
async function main() {
try {
console.log("Pinging...");
await fetchContestsData();
console.log("Pong!");
} catch (error) {
console.error("Error pinging the server:", error);
}
🤖 Prompt for AI Agents
In backend/chore: Update index.js for stability and error logging around lines
55 to 63, remove the debug statement that prints environment variables (delete
the line console.log(process.env.TEST);) to avoid leaking secrets to logs; if
you need local debug visibility, gate a non-sensitive message behind a
development-only flag (e.g., if (process.env.NODE_ENV === 'development')
console.log('debug')); otherwise simply delete the env log.

Comment on lines +97 to +135
  await dataSyncer.syncContests();
  setInterval(dataSyncer.syncContests, 90 * 60 * 1000);

  // Update contests data and sync contests data at regular intervals
  await contestSyncer.updateContests();
  setInterval(contestSyncer.updateContests, 60 * 60 * 1000);

  // Pinging the server every 13 minutes
  setInterval(
    async () => {
      try {
        await main();
        console.log("<=======Sent GET request to AWAKE");
      } catch (error) {
        console.error("Error Pinging", error);
      }
    },
    13 * 60 * 1000,
  );

  // Set up contest routes
  app.use("/contests", contestRoutes);
}

async function setupCommunityServer() {
  app.use("/community", communityRoutes);
}

async function setupHackathonServer() {
  await hackathonAPISyncer.syncHackathons();
  setInterval(hackathonAPISyncer.syncHackathons, 90 * 60 * 1000);

  // Update contests data and sync contests data at regular intervals
  await hackathonDBSyncer.updateHackathons();
  setInterval(hackathonDBSyncer.updateHackathons, 60 * 60 * 1000);

  // Set up hackathon routes
  app.use("/hackathons", hackathonRoutes);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle async interval failures explicitly.

setInterval invoked with async functions (syncContests, updateContests, syncHackathons, updateHackathons) drops the returned promise. Any rejection becomes an unhandled promise rejection, which your global handler turns into a process exit. Wrap each interval body in an async arrow and catch/log failures so a transient sync error doesn’t take down the server.

-  setInterval(dataSyncer.syncContests, 90 * 60 * 1000);
+  setInterval(async () => {
+    try {
+      await dataSyncer.syncContests();
+    } catch (err) {
+      console.error("Contest sync failed:", err);
+    }
+  }, 90 * 60 * 1000);
-
-  setInterval(contestSyncer.updateContests, 60 * 60 * 1000);
+  setInterval(async () => {
+    try {
+      await contestSyncer.updateContests();
+    } catch (err) {
+      console.error("Contest update failed:", err);
+    }
+  }, 60 * 60 * 1000);
@@
-  setInterval(hackathonAPISyncer.syncHackathons, 90 * 60 * 1000);
+  setInterval(async () => {
+    try {
+      await hackathonAPISyncer.syncHackathons();
+    } catch (err) {
+      console.error("Hackathon API sync failed:", err);
+    }
+  }, 90 * 60 * 1000);
-
-  setInterval(hackathonDBSyncer.updateHackathons, 60 * 60 * 1000);
+  setInterval(async () => {
+    try {
+      await hackathonDBSyncer.updateHackathons();
+    } catch (err) {
+      console.error("Hackathon DB update failed:", err);
+    }
+  }, 60 * 60 * 1000);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
  await dataSyncer.syncContests();
  setInterval(dataSyncer.syncContests, 90 * 60 * 1000);
  // Update contests data and sync contests data at regular intervals
  await contestSyncer.updateContests();
  setInterval(contestSyncer.updateContests, 60 * 60 * 1000);
  // Pinging the server every 13 minutes
  setInterval(
    async () => {
      try {
        await main();
        console.log("<=======Sent GET request to AWAKE");
      } catch (error) {
        console.error("Error Pinging", error);
      }
    },
    13 * 60 * 1000,
  );
  // Set up contest routes
  app.use("/contests", contestRoutes);
}
async function setupCommunityServer() {
  app.use("/community", communityRoutes);
}
async function setupHackathonServer() {
  await hackathonAPISyncer.syncHackathons();
  setInterval(hackathonAPISyncer.syncHackathons, 90 * 60 * 1000);
  // Update contests data and sync contests data at regular intervals
  await hackathonDBSyncer.updateHackathons();
  setInterval(hackathonDBSyncer.updateHackathons, 60 * 60 * 1000);
  // Set up hackathon routes
  app.use("/hackathons", hackathonRoutes);
}
await dataSyncer.syncContests();
setInterval(async () => {
try {
await dataSyncer.syncContests();
} catch (err) {
console.error("Contest sync failed:", err);
}
}, 90 * 60 * 1000);
// Update contests data and sync contests data at regular intervals
await contestSyncer.updateContests();
setInterval(async () => {
try {
await contestSyncer.updateContests();
} catch (err) {
console.error("Contest update failed:", err);
}
}, 60 * 60 * 1000);
// Pinging the server every 13 minutes
setInterval(
async () => {
try {
await main();
console.log("<=======Sent GET request to AWAKE");
} catch (error) {
console.error("Error Pinging", error);
}
},
13 * 60 * 1000,
);
// Set up contest routes
app.use("/contests", contestRoutes);
}
async function setupCommunityServer() {
app.use("/community", communityRoutes);
}
async function setupHackathonServer() {
await hackathonAPISyncer.syncHackathons();
setInterval(async () => {
try {
await hackathonAPISyncer.syncHackathons();
} catch (err) {
console.error("Hackathon API sync failed:", err);
}
}, 90 * 60 * 1000);
// Update contests data and sync contests data at regular intervals
await hackathonDBSyncer.updateHackathons();
setInterval(async () => {
try {
await hackathonDBSyncer.updateHackathons();
} catch (err) {
console.error("Hackathon DB update failed:", err);
}
}, 60 * 60 * 1000);
// Set up hackathon routes
app.use("/hackathons", hackathonRoutes);
}
🤖 Prompt for AI Agents
In backend/chore: Update index.js for stability and error logging around lines
97 to 135, several setInterval calls pass async functions directly which drops
returned promises and can turn transient rejections into unhandled promise
rejections; replace each setInterval(fnRef, ms) that currently uses an async
function reference (dataSyncer.syncContests, contestSyncer.updateContests,
hackathonAPISyncer.syncHackathons, hackathonDBSyncer.updateHackathons) with a
wrapper arrow that invokes the async call inside a try/catch and logs errors
(e.g., setInterval(async () => { try { await obj.method(); } catch (err) {
console.error("... failed", err); } }, ms)), ensuring the intervals still run at
the same intervals and adding clear error logging so failures don’t crash the
process.

Comment on lines +239 to +247
// Handling unhandled server errors (for Unhandled Promise Rejections)
process.on("unhandledRejection", (err) => {
  console.log(`Error: ${err.message}`);
  console.log("Shutting down the server due to Unhandled promise rejection");

  appServer.close(() => {
    process.exit(1);
  });
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against undefined appServer in shutdown handler.

If an unhandled rejection fires before app.listen succeeds, appServer is still undefined and calling appServer.close throws, undermining the shutdown path. Check that appServer exists before closing.

-process.on("unhandledRejection", (err) => {
+process.on("unhandledRejection", (err) => {
   console.log(`Error: ${err.message}`);
   console.log("Shutting down the server due to Unhandled promise rejection");
-
-  appServer.close(() => {
-    process.exit(1);
-  });
+  if (appServer && typeof appServer.close === "function") {
+    appServer.close(() => process.exit(1));
+  } else {
+    process.exit(1);
+  }
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Handling unhandled server errors (for Unhandled Promise Rejections)
process.on("unhandledRejection", (err) => {
  console.log(`Error: ${err.message}`);
  console.log("Shutting down the server due to Unhandled promise rejection");
  appServer.close(() => {
    process.exit(1);
  });
});
// Handling unhandled server errors (for Unhandled Promise Rejections)
process.on("unhandledRejection", (err) => {
console.log(`Error: ${err.message}`);
console.log("Shutting down the server due to Unhandled promise rejection");
if (appServer && typeof appServer.close === "function") {
appServer.close(() => process.exit(1));
} else {
process.exit(1);
}
});
🤖 Prompt for AI Agents
In backend/chore: Update index.js for stability and error logging around lines
239 to 247, the unhandledRejection handler assumes appServer is defined and
calls appServer.close(), which will throw if app.listen hasn't set appServer
yet; update the handler to check if appServer is truthy before calling close,
and if not, log that no server was running and call process.exit(1) (or set a
safe fallback), ensuring graceful shutdown only attempts close when appServer
exists and always exits afterwards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant