fix: dataforth API upload — unregistered model skip list, batch-500 fallback, FAIL filter
- UNREGISTERED_MODELS set: 9 model numbers not in Hoffman API catalog; skipped silently instead of generating errors - batch-500 fallback: when a bulk batch returns HTTP 500, retry each record individually so good records get stamped and only truly-bad records count as errors - FAIL-parameter filter: records with any FAIL on a parameter line are excluded from the push before the batch is assembled - notify.js integration: wired in existing notification module Files added: - projects/dataforth-dos/database/upload-to-api.js - projects/dataforth-dos/database/notify.js Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
71
projects/dataforth-dos/database/notify.js
Normal file
71
projects/dataforth-dos/database/notify.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Fire-and-forget alert notification module.
|
||||
* Email sending is not yet implemented (Entra app pending).
|
||||
* Logs a formatted preview of what would be emailed to stderr.
|
||||
* Never throws — callers do not need to guard this.
|
||||
*/
|
||||
|
||||
const os = require('os');
|
||||
|
||||
const TO = 'mike@azcomputerguru.com';
|
||||
const FROM = 'sysadmin@dataforth.com';
|
||||
const HOST = os.hostname();
|
||||
const PREFIX = '[NOTIFY]';
|
||||
const SEP_EQ = '='.repeat(60);
|
||||
const SEP_DAS = '-'.repeat(60);
|
||||
|
||||
/**
|
||||
* Log a formatted email preview to stderr.
|
||||
*
|
||||
* @param {string} subject - Email subject line (prefixed with [TestDataDB] automatically)
|
||||
* @param {object} [context={}]
|
||||
* @param {string} [context.stage] - Pipeline stage where the alert fired
|
||||
* @param {string} [context.error] - Error message or description
|
||||
* @param {string[]} [context.details] - Additional detail lines
|
||||
* @param {object} [context.stats] - Arbitrary stats object, serialized as JSON
|
||||
*/
|
||||
function alert(subject, context) {
|
||||
context = context || {};
|
||||
const lines = [];
|
||||
|
||||
lines.push(`${PREFIX} ${SEP_EQ}`);
|
||||
lines.push(`${PREFIX} TO: ${TO}`);
|
||||
lines.push(`${PREFIX} FROM: ${FROM} (pending Entra app)`);
|
||||
lines.push(`${PREFIX} SUBJECT: [TestDataDB] ${subject}`);
|
||||
lines.push(`${PREFIX} ${SEP_DAS}`);
|
||||
lines.push(`${PREFIX} Host: ${HOST}`);
|
||||
lines.push(`${PREFIX} Time: ${new Date().toISOString()}`);
|
||||
|
||||
if (context.stage !== undefined) {
|
||||
lines.push(`${PREFIX} Stage: ${context.stage}`);
|
||||
}
|
||||
|
||||
if (context.error !== undefined) {
|
||||
lines.push(`${PREFIX}`);
|
||||
lines.push(`${PREFIX} ${context.error}`);
|
||||
}
|
||||
|
||||
if (Array.isArray(context.details) && context.details.length > 0) {
|
||||
lines.push(`${PREFIX}`);
|
||||
for (const line of context.details) {
|
||||
lines.push(`${PREFIX} ${line}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (context.stats !== undefined) {
|
||||
lines.push(`${PREFIX} Stats: ${JSON.stringify(context.stats)}`);
|
||||
}
|
||||
|
||||
lines.push(`${PREFIX} ${SEP_EQ}`);
|
||||
lines.push(`${PREFIX} (email not sent — Entra app pending)`);
|
||||
|
||||
try {
|
||||
for (const line of lines) {
|
||||
process.stderr.write(line + '\n');
|
||||
}
|
||||
} catch (_) {
|
||||
// stderr write failure — nothing we can do
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { alert };
|
||||
Reference in New Issue
Block a user