feat(dm): migrated all the dm topics
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 4m26s

This commit is contained in:
2026-06-26 11:05:17 -05:00
parent 012a7e83b2
commit 47b149d1ea
48 changed files with 14156 additions and 44 deletions

View File

@@ -0,0 +1,168 @@
import { eq } from "drizzle-orm";
import { db } from "../db/db.controller.js";
import { prodAuditLogState } from "../db/schema/prodAuditlog.lastProcessed.schema.js";
import {
type NewProdAuditLog,
prodAuditLog,
} from "../db/schema/prodAuditlog.schema.js";
import { createLogger } from "../logger/logger.controller.js";
import { prodQuery } from "../prodSql/prodSqlQuery.controller.js";
import {
type SqlQuery,
sqlQuerySelector,
} from "../prodSql/prodSqlQuerySelector.utils.js";
import { delay } from "../utils/delay.utils.js";
import { returnFunc } from "../utils/returnHelper.utils.js";
import { tryCatch } from "../utils/trycatch.utils.js";
const log = createLogger({ module: "system", subModule: "prodAuditLog" });
let bufferProcessInProgress = false;
export const monitorProdAuditLog = async () => {
const auditLogQuery = sqlQuerySelector(`prod.auditlog`) as SqlQuery;
/*
get the last processed audit log so we can only pull the newest ones.
as the initial go will be zero we want to look at the top 1 so we only pull the most recent one.
*/
const latestAuditId = await db.select().from(prodAuditLogState).limit(1);
let auditQuery = auditLogQuery.query;
if (latestAuditId.length === 0) {
auditQuery = auditQuery
.replace(
"DECLARE @lastId BIGINT = [lstId];",
"--DECLARE @lastId BIGINT = [lstId];",
)
.replace("TOP (500)", "TOP (1)")
.replace("ASC", "DESC")
.replace("AND Id > @lastId", "--AND Id > @lastId");
} else {
auditQuery = auditQuery.replace(
"[lstId]",
`${latestAuditId[0]?.lastImportedAuditId}`,
);
}
const { data: queryRun, error } = await tryCatch(
prodQuery(auditQuery, `Running auditLog query`),
);
if (error) {
return returnFunc({
success: false,
level: "error",
module: "system",
subModule: "auditLog",
message: `Data for: AuditLog Failed`,
data: [error],
notify: false,
});
}
if (!queryRun.success) {
return returnFunc({
success: false,
level: "error",
module: "datamart",
subModule: "query",
message: queryRun.message,
data: queryRun.data,
notify: false,
});
}
const safeJsonParse = (value: unknown) => {
if (typeof value !== "string") return value;
try {
return JSON.parse(value);
} catch {
return { raw: value };
}
};
// remap everything lst logs to keep it easy to read
if (queryRun.data.length > 0) {
const auditRows = queryRun.data.map((r) => ({
auditId: r.Id,
actorName: r.ActorName,
auditCreatedDate: r.CreatedDateTime,
message: r.Message,
content: safeJsonParse(r.Content),
status: "pending",
processed: false,
retryCount: 0,
})) as NewProdAuditLog[];
await db.insert(prodAuditLog).values(auditRows).onConflictDoNothing();
const newestAuditId = queryRun.data.at(-1).Id;
await db
.insert(prodAuditLogState)
.values({
id: 1,
lastImportedAuditId: newestAuditId,
updatedAt: new Date(),
})
.onConflictDoUpdate({
target: prodAuditLogState.id,
set: {
lastImportedAuditId: newestAuditId,
updatedAt: new Date(),
},
});
}
};
export const bufferProcess = async (_data: unknown) => {
if (bufferProcessInProgress) {
log.debug({}, "[bufferProcess] already running, skipping trigger");
return;
}
bufferProcessInProgress = true;
try {
log.debug({}, "[bufferProcess] started");
while (true) {
const row = await db.query.prodAuditLog.findFirst({
where: (audit, { eq }) => eq(audit.processed, false),
orderBy: (audit, { asc }) => [asc(audit.auditId)],
});
if (!row) {
log.debug({}, "[bufferProcess] no pending rows");
break;
}
log.debug({}, "[bufferProcess] processing audit row", row.auditId);
// tiny delay so you can visually validate the flow
await delay(250);
// TODO add in case statement to do things, if thing returns good then say good if fails then we set to error and let it retry later.
// for items that don't fall in the case will auto set status to success
// console.log(row.message.split("."));
await db
.update(prodAuditLog)
.set({
processed: true,
status: "success",
processedAt: new Date(),
updatedAt: new Date(),
})
.where(eq(prodAuditLog.id, row.id));
}
} catch (error) {
log.error({ stack: error }, "[bufferProcess] failed");
} finally {
bufferProcessInProgress = false;
log.debug({}, "[bufferProcess] finished");
}
};