@astralibx/email-rule-engine 12.0.1 → 12.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +39 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.mjs +39 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -192,6 +192,11 @@ interface BeforeSendParams {
|
|
|
192
192
|
email: string;
|
|
193
193
|
name: string;
|
|
194
194
|
};
|
|
195
|
+
context: {
|
|
196
|
+
ruleId: string;
|
|
197
|
+
templateId: string;
|
|
198
|
+
runId: string;
|
|
199
|
+
};
|
|
195
200
|
}
|
|
196
201
|
interface BeforeSendResult {
|
|
197
202
|
htmlBody: string;
|
|
@@ -258,27 +263,39 @@ interface EmailRuleEngineConfig {
|
|
|
258
263
|
onRunStart?: (info: {
|
|
259
264
|
rulesCount: number;
|
|
260
265
|
triggeredBy: string;
|
|
266
|
+
runId: string;
|
|
261
267
|
}) => void;
|
|
262
268
|
onRuleStart?: (info: {
|
|
263
269
|
ruleId: string;
|
|
264
270
|
ruleName: string;
|
|
265
271
|
matchedCount: number;
|
|
272
|
+
templateId: string;
|
|
273
|
+
runId: string;
|
|
266
274
|
}) => void;
|
|
267
275
|
onSend?: (info: {
|
|
268
276
|
ruleId: string;
|
|
269
277
|
ruleName: string;
|
|
270
278
|
email: string;
|
|
271
279
|
status: 'sent' | 'error' | 'skipped' | 'invalid' | 'throttled';
|
|
280
|
+
accountId: string;
|
|
281
|
+
templateId: string;
|
|
282
|
+
runId: string;
|
|
283
|
+
subjectIndex: number;
|
|
284
|
+
bodyIndex: number;
|
|
285
|
+
failureReason?: string;
|
|
272
286
|
}) => void;
|
|
273
287
|
onRuleComplete?: (info: {
|
|
274
288
|
ruleId: string;
|
|
275
289
|
ruleName: string;
|
|
276
290
|
stats: RuleRunStats;
|
|
291
|
+
templateId: string;
|
|
292
|
+
runId: string;
|
|
277
293
|
}) => void;
|
|
278
294
|
onRunComplete?: (info: {
|
|
279
295
|
duration: number;
|
|
280
296
|
totalStats: RuleRunStats;
|
|
281
297
|
perRuleStats: PerRuleStats[];
|
|
298
|
+
runId: string;
|
|
282
299
|
}) => void;
|
|
283
300
|
beforeSend?: (params: BeforeSendParams) => Promise<BeforeSendResult>;
|
|
284
301
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -192,6 +192,11 @@ interface BeforeSendParams {
|
|
|
192
192
|
email: string;
|
|
193
193
|
name: string;
|
|
194
194
|
};
|
|
195
|
+
context: {
|
|
196
|
+
ruleId: string;
|
|
197
|
+
templateId: string;
|
|
198
|
+
runId: string;
|
|
199
|
+
};
|
|
195
200
|
}
|
|
196
201
|
interface BeforeSendResult {
|
|
197
202
|
htmlBody: string;
|
|
@@ -258,27 +263,39 @@ interface EmailRuleEngineConfig {
|
|
|
258
263
|
onRunStart?: (info: {
|
|
259
264
|
rulesCount: number;
|
|
260
265
|
triggeredBy: string;
|
|
266
|
+
runId: string;
|
|
261
267
|
}) => void;
|
|
262
268
|
onRuleStart?: (info: {
|
|
263
269
|
ruleId: string;
|
|
264
270
|
ruleName: string;
|
|
265
271
|
matchedCount: number;
|
|
272
|
+
templateId: string;
|
|
273
|
+
runId: string;
|
|
266
274
|
}) => void;
|
|
267
275
|
onSend?: (info: {
|
|
268
276
|
ruleId: string;
|
|
269
277
|
ruleName: string;
|
|
270
278
|
email: string;
|
|
271
279
|
status: 'sent' | 'error' | 'skipped' | 'invalid' | 'throttled';
|
|
280
|
+
accountId: string;
|
|
281
|
+
templateId: string;
|
|
282
|
+
runId: string;
|
|
283
|
+
subjectIndex: number;
|
|
284
|
+
bodyIndex: number;
|
|
285
|
+
failureReason?: string;
|
|
272
286
|
}) => void;
|
|
273
287
|
onRuleComplete?: (info: {
|
|
274
288
|
ruleId: string;
|
|
275
289
|
ruleName: string;
|
|
276
290
|
stats: RuleRunStats;
|
|
291
|
+
templateId: string;
|
|
292
|
+
runId: string;
|
|
277
293
|
}) => void;
|
|
278
294
|
onRunComplete?: (info: {
|
|
279
295
|
duration: number;
|
|
280
296
|
totalStats: RuleRunStats;
|
|
281
297
|
perRuleStats: PerRuleStats[];
|
|
298
|
+
runId: string;
|
|
282
299
|
}) => void;
|
|
283
300
|
beforeSend?: (params: BeforeSendParams) => Promise<BeforeSendResult>;
|
|
284
301
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1014,7 +1014,7 @@ var RuleRunnerService = class {
|
|
|
1014
1014
|
}
|
|
1015
1015
|
return true;
|
|
1016
1016
|
});
|
|
1017
|
-
this.config.hooks?.onRunStart?.({ rulesCount: activeRules.length, triggeredBy });
|
|
1017
|
+
this.config.hooks?.onRunStart?.({ rulesCount: activeRules.length, triggeredBy, runId });
|
|
1018
1018
|
await this.updateRunProgress(runId, {
|
|
1019
1019
|
progress: { rulesTotal: activeRules.length, rulesCompleted: 0, sent: 0, failed: 0, skipped: 0, invalid: 0 }
|
|
1020
1020
|
});
|
|
@@ -1103,7 +1103,7 @@ var RuleRunnerService = class {
|
|
|
1103
1103
|
status: runStatus
|
|
1104
1104
|
});
|
|
1105
1105
|
await this.updateRunProgress(runId, { status: runStatus, currentRule: "", elapsed: Date.now() - runStartTime });
|
|
1106
|
-
this.config.hooks?.onRunComplete?.({ duration: Date.now() - runStartTime, totalStats, perRuleStats });
|
|
1106
|
+
this.config.hooks?.onRunComplete?.({ duration: Date.now() - runStartTime, totalStats, perRuleStats, runId });
|
|
1107
1107
|
this.logger.info("Rule run completed", {
|
|
1108
1108
|
triggeredBy,
|
|
1109
1109
|
rulesProcessed: activeRules.length,
|
|
@@ -1142,7 +1142,7 @@ var RuleRunnerService = class {
|
|
|
1142
1142
|
stats.matched = emailsToProcess.length;
|
|
1143
1143
|
const ruleId = rule._id.toString();
|
|
1144
1144
|
const templateId = rule.templateId.toString();
|
|
1145
|
-
this.config.hooks?.onRuleStart?.({ ruleId, ruleName: rule.name, matchedCount: emailsToProcess.length });
|
|
1145
|
+
this.config.hooks?.onRuleStart?.({ ruleId, ruleName: rule.name, matchedCount: emailsToProcess.length, templateId, runId: runId || "" });
|
|
1146
1146
|
if (emailsToProcess.length === 0) return stats;
|
|
1147
1147
|
const identifierResults = await processInChunks(
|
|
1148
1148
|
emailsToProcess,
|
|
@@ -1187,7 +1187,7 @@ var RuleRunnerService = class {
|
|
|
1187
1187
|
const identifier = identifierMap.get(email);
|
|
1188
1188
|
if (!identifier) {
|
|
1189
1189
|
stats.skipped++;
|
|
1190
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "invalid" });
|
|
1190
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "invalid", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "invalid email" });
|
|
1191
1191
|
continue;
|
|
1192
1192
|
}
|
|
1193
1193
|
const dedupKey = identifier.id;
|
|
@@ -1195,27 +1195,27 @@ var RuleRunnerService = class {
|
|
|
1195
1195
|
if (lastSend) {
|
|
1196
1196
|
if (rule.sendOnce && !rule.resendAfterDays) {
|
|
1197
1197
|
stats.skipped++;
|
|
1198
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1198
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "send once" });
|
|
1199
1199
|
continue;
|
|
1200
1200
|
}
|
|
1201
1201
|
if (rule.resendAfterDays) {
|
|
1202
1202
|
const daysSince = (Date.now() - new Date(lastSend.sentAt).getTime()) / MS_PER_DAY;
|
|
1203
1203
|
if (daysSince < rule.resendAfterDays) {
|
|
1204
1204
|
stats.skipped++;
|
|
1205
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1205
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "resend too soon" });
|
|
1206
1206
|
continue;
|
|
1207
1207
|
}
|
|
1208
1208
|
} else {
|
|
1209
1209
|
stats.skipped++;
|
|
1210
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1210
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "send once" });
|
|
1211
1211
|
continue;
|
|
1212
1212
|
}
|
|
1213
1213
|
}
|
|
1214
|
-
if (!this.checkThrottle(rule, dedupKey, email, throttleMap, throttleConfig, stats)) continue;
|
|
1214
|
+
if (!this.checkThrottle(rule, dedupKey, email, throttleMap, throttleConfig, stats, templateId, runId)) continue;
|
|
1215
1215
|
const agentSelection = await this.config.adapters.selectAgent(identifier.id, { ruleId, templateId });
|
|
1216
1216
|
if (!agentSelection) {
|
|
1217
1217
|
stats.skipped++;
|
|
1218
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1218
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "no account available" });
|
|
1219
1219
|
continue;
|
|
1220
1220
|
}
|
|
1221
1221
|
const user = { _id: identifier.id, email };
|
|
@@ -1253,6 +1253,11 @@ var RuleRunnerService = class {
|
|
|
1253
1253
|
id: dedupKey,
|
|
1254
1254
|
email,
|
|
1255
1255
|
name: ""
|
|
1256
|
+
},
|
|
1257
|
+
context: {
|
|
1258
|
+
ruleId,
|
|
1259
|
+
templateId,
|
|
1260
|
+
runId: runId || ""
|
|
1256
1261
|
}
|
|
1257
1262
|
});
|
|
1258
1263
|
finalHtml = modified.htmlBody;
|
|
@@ -1261,7 +1266,7 @@ var RuleRunnerService = class {
|
|
|
1261
1266
|
} catch (hookErr) {
|
|
1262
1267
|
this.logger.error(`beforeSend hook failed for email ${email}: ${hookErr.message}`);
|
|
1263
1268
|
stats.errorCount++;
|
|
1264
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "error" });
|
|
1269
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "error", accountId: agentSelection.accountId, templateId, runId: runId || "", subjectIndex: si, bodyIndex: bi, failureReason: hookErr.message });
|
|
1265
1270
|
continue;
|
|
1266
1271
|
}
|
|
1267
1272
|
}
|
|
@@ -1289,7 +1294,7 @@ var RuleRunnerService = class {
|
|
|
1289
1294
|
lastSentDate: /* @__PURE__ */ new Date()
|
|
1290
1295
|
});
|
|
1291
1296
|
stats.sent++;
|
|
1292
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "sent" });
|
|
1297
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "sent", accountId: agentSelection.accountId, templateId, runId: runId || "", subjectIndex: si, bodyIndex: bi });
|
|
1293
1298
|
totalProcessed++;
|
|
1294
1299
|
if (runId && totalProcessed % 10 === 0) {
|
|
1295
1300
|
await this.updateRunSendProgress(runId, stats);
|
|
@@ -1304,7 +1309,7 @@ var RuleRunnerService = class {
|
|
|
1304
1309
|
}
|
|
1305
1310
|
} catch (err) {
|
|
1306
1311
|
stats.errorCount++;
|
|
1307
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "error" });
|
|
1312
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "error", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: err.message || "unknown error" });
|
|
1308
1313
|
this.logger.error(`Rule "${rule.name}" failed for identifier ${email}`, { error: err });
|
|
1309
1314
|
}
|
|
1310
1315
|
}
|
|
@@ -1327,7 +1332,7 @@ var RuleRunnerService = class {
|
|
|
1327
1332
|
this.logger.info(`Rule '${rule.name}' auto-disabled \u2014 all identifiers processed`);
|
|
1328
1333
|
}
|
|
1329
1334
|
}
|
|
1330
|
-
this.config.hooks?.onRuleComplete?.({ ruleId, ruleName: rule.name, stats });
|
|
1335
|
+
this.config.hooks?.onRuleComplete?.({ ruleId, ruleName: rule.name, stats, templateId, runId: runId || "" });
|
|
1331
1336
|
return stats;
|
|
1332
1337
|
}
|
|
1333
1338
|
async executeQueryMode(rule, template, throttleMap, throttleConfig, stats, runId) {
|
|
@@ -1340,7 +1345,7 @@ var RuleRunnerService = class {
|
|
|
1340
1345
|
return stats;
|
|
1341
1346
|
}
|
|
1342
1347
|
stats.matched = users.length;
|
|
1343
|
-
this.config.hooks?.onRuleStart?.({ ruleId: rule._id.toString(), ruleName: rule.name, matchedCount: users.length });
|
|
1348
|
+
this.config.hooks?.onRuleStart?.({ ruleId: rule._id.toString(), ruleName: rule.name, matchedCount: users.length, templateId: rule.templateId.toString(), runId: runId || "" });
|
|
1344
1349
|
if (users.length === 0) return stats;
|
|
1345
1350
|
const userIds = users.map((u) => u._id?.toString()).filter(Boolean);
|
|
1346
1351
|
const emails = users.map((u) => u.email).filter(Boolean);
|
|
@@ -1389,40 +1394,40 @@ var RuleRunnerService = class {
|
|
|
1389
1394
|
const email = user.email;
|
|
1390
1395
|
if (!userId || !email) {
|
|
1391
1396
|
stats.skipped++;
|
|
1392
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email: email || "unknown", status: "invalid" });
|
|
1397
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email: email || "unknown", status: "invalid", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "invalid email" });
|
|
1393
1398
|
continue;
|
|
1394
1399
|
}
|
|
1395
1400
|
const lastSend = sendMap.get(userId);
|
|
1396
1401
|
if (lastSend) {
|
|
1397
1402
|
if (rule.sendOnce && !rule.resendAfterDays) {
|
|
1398
1403
|
stats.skipped++;
|
|
1399
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1404
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "send once" });
|
|
1400
1405
|
continue;
|
|
1401
1406
|
}
|
|
1402
1407
|
if (rule.resendAfterDays) {
|
|
1403
1408
|
const daysSince = (Date.now() - new Date(lastSend.sentAt).getTime()) / MS_PER_DAY;
|
|
1404
1409
|
if (daysSince < rule.resendAfterDays) {
|
|
1405
1410
|
stats.skipped++;
|
|
1406
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1411
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "resend too soon" });
|
|
1407
1412
|
continue;
|
|
1408
1413
|
}
|
|
1409
1414
|
} else {
|
|
1410
1415
|
stats.skipped++;
|
|
1411
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1416
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "send once" });
|
|
1412
1417
|
continue;
|
|
1413
1418
|
}
|
|
1414
1419
|
}
|
|
1415
1420
|
const identifier = identifierMap.get(email.toLowerCase().trim());
|
|
1416
1421
|
if (!identifier) {
|
|
1417
1422
|
stats.skipped++;
|
|
1418
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "invalid" });
|
|
1423
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "invalid", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "invalid email" });
|
|
1419
1424
|
continue;
|
|
1420
1425
|
}
|
|
1421
|
-
if (!this.checkThrottle(rule, userId, email, throttleMap, throttleConfig, stats)) continue;
|
|
1426
|
+
if (!this.checkThrottle(rule, userId, email, throttleMap, throttleConfig, stats, templateId, runId)) continue;
|
|
1422
1427
|
const agentSelection = await this.config.adapters.selectAgent(identifier.id, { ruleId, templateId });
|
|
1423
1428
|
if (!agentSelection) {
|
|
1424
1429
|
stats.skipped++;
|
|
1425
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped" });
|
|
1430
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "skipped", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "no account available" });
|
|
1426
1431
|
continue;
|
|
1427
1432
|
}
|
|
1428
1433
|
const resolvedData = this.config.adapters.resolveData(user);
|
|
@@ -1459,6 +1464,11 @@ var RuleRunnerService = class {
|
|
|
1459
1464
|
id: String(userId),
|
|
1460
1465
|
email,
|
|
1461
1466
|
name: String(user.name || user.firstName || "")
|
|
1467
|
+
},
|
|
1468
|
+
context: {
|
|
1469
|
+
ruleId,
|
|
1470
|
+
templateId,
|
|
1471
|
+
runId: runId || ""
|
|
1462
1472
|
}
|
|
1463
1473
|
});
|
|
1464
1474
|
finalHtml = modified.htmlBody;
|
|
@@ -1467,7 +1477,7 @@ var RuleRunnerService = class {
|
|
|
1467
1477
|
} catch (hookErr) {
|
|
1468
1478
|
this.logger.error(`beforeSend hook failed for email ${email}: ${hookErr.message}`);
|
|
1469
1479
|
stats.errorCount++;
|
|
1470
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "error" });
|
|
1480
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "error", accountId: agentSelection.accountId, templateId, runId: runId || "", subjectIndex: si, bodyIndex: bi, failureReason: hookErr.message });
|
|
1471
1481
|
continue;
|
|
1472
1482
|
}
|
|
1473
1483
|
}
|
|
@@ -1495,7 +1505,7 @@ var RuleRunnerService = class {
|
|
|
1495
1505
|
lastSentDate: /* @__PURE__ */ new Date()
|
|
1496
1506
|
});
|
|
1497
1507
|
stats.sent++;
|
|
1498
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "sent" });
|
|
1508
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email, status: "sent", accountId: agentSelection.accountId, templateId, runId: runId || "", subjectIndex: si, bodyIndex: bi });
|
|
1499
1509
|
totalProcessed++;
|
|
1500
1510
|
if (runId && totalProcessed % 10 === 0) {
|
|
1501
1511
|
await this.updateRunSendProgress(runId, stats);
|
|
@@ -1510,7 +1520,7 @@ var RuleRunnerService = class {
|
|
|
1510
1520
|
}
|
|
1511
1521
|
} catch (err) {
|
|
1512
1522
|
stats.errorCount++;
|
|
1513
|
-
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email: user.email || "unknown", status: "error" });
|
|
1523
|
+
this.config.hooks?.onSend?.({ ruleId, ruleName: rule.name, email: user.email || "unknown", status: "error", accountId: "", templateId, runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: err.message || "unknown error" });
|
|
1514
1524
|
this.logger.error(`Rule "${rule.name}" failed for user ${user._id?.toString()}`, { error: err });
|
|
1515
1525
|
}
|
|
1516
1526
|
}
|
|
@@ -1518,27 +1528,27 @@ var RuleRunnerService = class {
|
|
|
1518
1528
|
$set: { lastRunAt: /* @__PURE__ */ new Date(), lastRunStats: stats },
|
|
1519
1529
|
$inc: { totalSent: stats.sent, totalSkipped: stats.skipped }
|
|
1520
1530
|
});
|
|
1521
|
-
this.config.hooks?.onRuleComplete?.({ ruleId, ruleName: rule.name, stats });
|
|
1531
|
+
this.config.hooks?.onRuleComplete?.({ ruleId, ruleName: rule.name, stats, templateId, runId: runId || "" });
|
|
1522
1532
|
return stats;
|
|
1523
1533
|
}
|
|
1524
|
-
checkThrottle(rule, userId, email, throttleMap, config, stats) {
|
|
1534
|
+
checkThrottle(rule, userId, email, throttleMap, config, stats, templateId, runId) {
|
|
1525
1535
|
if (rule.emailType === EMAIL_TYPE.Transactional || rule.bypassThrottle) return true;
|
|
1526
1536
|
const userThrottle = throttleMap.get(userId) || { today: 0, thisWeek: 0, lastSentDate: null };
|
|
1527
1537
|
if (userThrottle.today >= config.maxPerUserPerDay) {
|
|
1528
1538
|
stats.skippedByThrottle++;
|
|
1529
|
-
this.config.hooks?.onSend?.({ ruleId: rule._id.toString(), ruleName: rule.name, email, status: "throttled" });
|
|
1539
|
+
this.config.hooks?.onSend?.({ ruleId: rule._id.toString(), ruleName: rule.name, email, status: "throttled", accountId: "", templateId: templateId || "", runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "daily throttle limit" });
|
|
1530
1540
|
return false;
|
|
1531
1541
|
}
|
|
1532
1542
|
if (userThrottle.thisWeek >= config.maxPerUserPerWeek) {
|
|
1533
1543
|
stats.skippedByThrottle++;
|
|
1534
|
-
this.config.hooks?.onSend?.({ ruleId: rule._id.toString(), ruleName: rule.name, email, status: "throttled" });
|
|
1544
|
+
this.config.hooks?.onSend?.({ ruleId: rule._id.toString(), ruleName: rule.name, email, status: "throttled", accountId: "", templateId: templateId || "", runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "weekly throttle limit" });
|
|
1535
1545
|
return false;
|
|
1536
1546
|
}
|
|
1537
1547
|
if (userThrottle.lastSentDate) {
|
|
1538
1548
|
const daysSinceLastSend = (Date.now() - userThrottle.lastSentDate.getTime()) / MS_PER_DAY;
|
|
1539
1549
|
if (daysSinceLastSend < config.minGapDays) {
|
|
1540
1550
|
stats.skippedByThrottle++;
|
|
1541
|
-
this.config.hooks?.onSend?.({ ruleId: rule._id.toString(), ruleName: rule.name, email, status: "throttled" });
|
|
1551
|
+
this.config.hooks?.onSend?.({ ruleId: rule._id.toString(), ruleName: rule.name, email, status: "throttled", accountId: "", templateId: templateId || "", runId: runId || "", subjectIndex: -1, bodyIndex: -1, failureReason: "min gap days" });
|
|
1542
1552
|
return false;
|
|
1543
1553
|
}
|
|
1544
1554
|
}
|