Send the campaign batch

Node · Node · intermediate · greenfield

Adds the campaign batch sender: a fixed pool of 5 workers walks the recipient list off a shared cursor, so at most 5 sends are ever in flight regardless of list size. Failures are collected per recipient without stopping the batch, and the function resolves with the sent/failed breakdown.

Marketing service for a newsletter product; the provider enforces the 5-concurrent-requests limit with hard 429s.

Requirements

Files touched

--- src/campaigns/sendCampaign.js
+const { sendEmail } = require('./emailClient');
+
+const POOL_SIZE = 5;
+
+/**
+ * Send one email per recipient with at most POOL_SIZE requests in flight.
+ * One bad address never aborts the batch.
+ */
+async function sendCampaign(recipients, message) {
+  const sent = [];
+  const failed = [];
+  let next = 0;
+
+  async function worker() {
+    while (next < recipients.length) {
+      const recipient = recipients[next];
+      next += 1;
+      try {
+        await sendEmail(recipient.email, message);
+        sent.push(recipient.email);
+      } catch (error) {
+        failed.push({ email: recipient.email, error: error.message });
+      }
+    }
+  }
+
+  const workerCount = Math.min(POOL_SIZE, recipients.length);
+  const workers = [];
+  for (let i = 0; i < workerCount; i += 1) {

Review this PR

Node practice