this means that if we drag down a bunch of loads we wont instantly change to arrived we will need to have a single scan before we do this
727 lines
21 KiB
TypeScript
727 lines
21 KiB
TypeScript
import axios from "axios";
|
|
import { addHours } from "date-fns";
|
|
import { formatInTimeZone } from "date-fns-tz";
|
|
import { eq, sql } from "drizzle-orm";
|
|
import { db } from "../db/db.controller.js";
|
|
import { opendockApt } from "../db/schema/opendock_apt.schema.js";
|
|
import { settings } from "../db/schema/settings.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 { createCronJob } from "../utils/croner.utils.js";
|
|
import { delay } from "../utils/delay.utils.js";
|
|
import { returnFunc } from "../utils/returnHelper.utils.js";
|
|
import { tryCatch } from "../utils/trycatch.utils.js";
|
|
import { getToken, odToken } from "./opendock.utils.js";
|
|
|
|
type Releases = {
|
|
ReleaseNumber: number;
|
|
DeliveryState: number;
|
|
DeliveryDate: Date;
|
|
LineItemHumanReadableId: number;
|
|
ArticleAlias: string;
|
|
LoadingUnits: string;
|
|
Quantity: number;
|
|
LineItemArticleWeight: number;
|
|
CustomerReleaseNumber: string;
|
|
DeliveryAddressDescription: string;
|
|
DeliveryAddressHumanReadableId: string;
|
|
AdditionalInformation1: string;
|
|
};
|
|
|
|
// TODO: add these docs into the db
|
|
const actaulDocks = [
|
|
{ name: "cermac", dockId: "bcb17fae-0b1a-47a7-9fbf-594c5ebccce9" },
|
|
{ name: "matrix", dockId: "3e32cbfc-49f4-4138-b491-9d5df9c94754" },
|
|
{ name: "gerber", dockId: "9109e789-6c15-4cd9-87cb-de1b18627b6d" },
|
|
{ name: "rb", dockId: "6be02526-6183-4789-a73f-e0aa155e6d1e" },
|
|
];
|
|
const timeZone = process.env.TIMEZONE as string;
|
|
const TWENTY_FOUR_HOURS = 24 * 60 * 60 * 1000;
|
|
const log = createLogger({ module: "opendock", subModule: "releaseMonitor" });
|
|
|
|
// making the cron more safe when it comes to buffer stuff
|
|
let opendockSyncRunning = false;
|
|
|
|
let lastCheck = formatInTimeZone(
|
|
new Date().toISOString(),
|
|
timeZone,
|
|
"yyyy-MM-dd HH:mm:ss",
|
|
);
|
|
|
|
// const lastCheck = formatInTimeZone(
|
|
// new Date().toISOString(),
|
|
// `America/New_York`, //TODO: Pull timezone from the .env last as process.env.TIME_ZONE is not working so need to figure itout
|
|
// "yyyy-MM-dd HH:mm:ss",
|
|
// );
|
|
|
|
//const queue: unknown[] = [];
|
|
//const isProcessing: boolean = false;
|
|
|
|
// const parseDbDate = (value: string | Date) => {
|
|
// if (value instanceof Date) return value;
|
|
|
|
// // normalize "2026-04-08 13:10:43.280" -> "2026-04-08T13:10:43.280"
|
|
// const normalized = value.replace(" ", "T");
|
|
|
|
// // interpret that wall-clock time as America/New_York
|
|
// return fromZonedTime(normalized, timeZone);
|
|
// };
|
|
|
|
const postRelease = async (release: Releases) => {
|
|
log.debug({}, `Release: ${release.ReleaseNumber} is about to be validated`);
|
|
if (!odToken.odToken) {
|
|
log.info({}, "Getting Auth Token");
|
|
await getToken();
|
|
}
|
|
|
|
if (
|
|
new Date(odToken.tokenDate || Date.now()).getTime() <
|
|
Date.now() - TWENTY_FOUR_HOURS
|
|
) {
|
|
log.info({}, "Refreshing Auth Token");
|
|
await getToken();
|
|
}
|
|
|
|
// load validation checks
|
|
const defaultDock = await db.query.settings.findFirst({
|
|
where: (u, { eq }) => eq(u.name, "defaultLoadType"),
|
|
});
|
|
|
|
// check if the release has the loadtype in it
|
|
const releaseLoadtypeCheck = (release.AdditionalInformation1 ?? "")
|
|
.toLowerCase()
|
|
.split(",")
|
|
.map((x) => x.trim())
|
|
.includes("drop");
|
|
|
|
// allowed to schedule now, as long as we see od in here somewhere
|
|
const releaseOkToSchedule = (release.AdditionalInformation1 ?? "")
|
|
.toLowerCase()
|
|
.split(",")
|
|
.map((x) => x.trim())
|
|
.includes("od");
|
|
|
|
// dock was sent over
|
|
const releaseDockInfo = actaulDocks.some((dock) =>
|
|
(release.AdditionalInformation1 ?? "")
|
|
.toLowerCase()
|
|
.split(",")
|
|
.map((x) => x.trim())
|
|
.includes(dock.name.toLowerCase()),
|
|
);
|
|
|
|
const opendDockArticleCheck = await db.query.opendockArticleSetup.findFirst({
|
|
where: (table, { and, eq }) =>
|
|
and(
|
|
eq(table.av, release.LineItemHumanReadableId),
|
|
eq(table.customer, release.DeliveryAddressHumanReadableId),
|
|
),
|
|
});
|
|
|
|
// selected dock
|
|
const releaseDocks = (release.AdditionalInformation1 ?? "")
|
|
.toLowerCase()
|
|
.split(",")
|
|
.map((x) => x.trim());
|
|
|
|
const matchedDock = actaulDocks.find((dock) =>
|
|
releaseDocks.includes(dock.name.toLowerCase()),
|
|
);
|
|
|
|
const setDock =
|
|
// validate we dont have the dock in the release
|
|
releaseDockInfo
|
|
? matchedDock?.dockId
|
|
: // validate we dont have the dock in the aritcle check
|
|
(actaulDocks.find((d) => d.name === opendDockArticleCheck?.dock)
|
|
?.dockId ?? process.env.DEFAULT_DOCK);
|
|
|
|
// TODO: add in docks from lst db here to make it more universal for the team
|
|
/**
|
|
* ReleaseState
|
|
* 0 = open
|
|
* 1 = planned
|
|
* 2 = CustomCanceled
|
|
* 4 = internally canceled
|
|
*/
|
|
|
|
/**
|
|
* DeliveryState
|
|
* 0 = open
|
|
* 1 = inprogress
|
|
* 2 = loading
|
|
* 3 = partly shipped
|
|
* 4 = delivered
|
|
*/
|
|
|
|
const newDockApt = {
|
|
status:
|
|
release.DeliveryState === 0 || release.DeliveryState === 1
|
|
? "Scheduled"
|
|
: release.DeliveryState === 2
|
|
? "InProgress"
|
|
: release.DeliveryState === 3 // this will consider finished and if a correction needs made to the bol we need to cancel and reactivate the order
|
|
? "Completed"
|
|
: release.DeliveryState === 4 && "Completed",
|
|
userId: process.env.DEFAULT_CARRIER, // this should be the carrierid
|
|
loadTypeId: process.env.DEFAULT_LOAD_TYPE, // well get this and make it a default one
|
|
// TODO: look in the remarks in the release and if its says
|
|
dockId: setDock, // this the warehouse we want it in to start out
|
|
refNumbers: [release.ReleaseNumber],
|
|
//refNumber: release.ReleaseNumber,
|
|
start: release.DeliveryDate,
|
|
end: addHours(release.DeliveryDate, 1),
|
|
notes: "",
|
|
ccEmails: [""],
|
|
muteNotifications: true,
|
|
metadata: {
|
|
externalValidationFailed: false,
|
|
externalValidationErrorMessage: null,
|
|
},
|
|
units: null,
|
|
customFields: [
|
|
{
|
|
name: "strCustomer",
|
|
type: "str",
|
|
label: "Customer",
|
|
value: `${release.DeliveryAddressDescription}`,
|
|
description: "Who is the customer ",
|
|
placeholder: "",
|
|
dropDownValues: [],
|
|
minLengthOrValue: 1,
|
|
hiddenFromCarrier: false,
|
|
requiredForCarrier: false,
|
|
requiredForWarehouse: false,
|
|
},
|
|
{
|
|
name: "strArticle",
|
|
type: "str",
|
|
label: "Article",
|
|
value: `${release.LineItemHumanReadableId} - ${release.ArticleAlias}`,
|
|
description: "What bottle are we sending ",
|
|
placeholder: "",
|
|
dropDownValues: [],
|
|
minLengthOrValue: 1,
|
|
hiddenFromCarrier: false,
|
|
requiredForCarrier: false,
|
|
requiredForWarehouse: false,
|
|
},
|
|
{
|
|
name: "intPallet Count",
|
|
type: "int",
|
|
label: "Pallet Count",
|
|
value: parseInt(release.LoadingUnits, 10), // do we really want to update this if its partial load as it should have been the full amount?
|
|
description: "How many pallets",
|
|
placeholder: "22",
|
|
dropDownValues: [],
|
|
minLengthOrValue: 1,
|
|
hiddenFromCarrier: false,
|
|
requiredForCarrier: false,
|
|
requiredForWarehouse: false,
|
|
},
|
|
{
|
|
name: "strTotal Weight",
|
|
type: "str",
|
|
label: "Total Weight",
|
|
value: `${(((release.Quantity * release.LineItemArticleWeight) / 1000) * 2.20462).toFixed(2)}`,
|
|
description: "What is the total weight of the load",
|
|
placeholder: "",
|
|
dropDownValues: [],
|
|
minLengthOrValue: 1,
|
|
hiddenFromCarrier: false,
|
|
requiredForCarrier: false,
|
|
requiredForWarehouse: false,
|
|
},
|
|
{
|
|
name: "strCustomer ReleaseNumber",
|
|
type: "str",
|
|
label: "Customer Release Number",
|
|
value: `${release.CustomerReleaseNumber}`,
|
|
description: "What is the customer release number",
|
|
placeholder: "",
|
|
dropDownValues: [],
|
|
minLengthOrValue: 1,
|
|
hiddenFromCarrier: false,
|
|
requiredForCarrier: false,
|
|
requiredForWarehouse: false,
|
|
},
|
|
],
|
|
};
|
|
|
|
// TODO: pull the current added releases from the db and if one matches then we want to get its id and run the update vs create
|
|
const { data: existingApt, error: aptError } = await tryCatch(
|
|
db
|
|
.select()
|
|
.from(opendockApt)
|
|
.where(eq(opendockApt.release, release.ReleaseNumber))
|
|
.limit(1),
|
|
);
|
|
if (aptError) {
|
|
log.error({ error: aptError }, "Error getting apt data");
|
|
// TODO: send an error email on this one as it will cause issues
|
|
return;
|
|
}
|
|
|
|
const existing = existingApt[0];
|
|
|
|
//console.log(releaseCheck);
|
|
|
|
if (existing) {
|
|
const id = existing.openDockAptId;
|
|
|
|
if (
|
|
(releaseLoadtypeCheck ||
|
|
opendDockArticleCheck?.loadType === "drop" ||
|
|
defaultDock?.value === "drop") &&
|
|
(release.DeliveryState === 0 || release.DeliveryState === 2)
|
|
) {
|
|
const setArrival = { ...newDockApt, status: "Arrived" };
|
|
|
|
// set to arrived
|
|
try {
|
|
const response = await axios.patch(
|
|
`${process.env.OPENDOCK_URL}/appointment/${id}`,
|
|
setArrival,
|
|
{
|
|
headers: {
|
|
"content-type": "application/json; charset=utf-8",
|
|
Authorization: `Bearer ${odToken.odToken}`,
|
|
},
|
|
},
|
|
);
|
|
|
|
if (response.status === 400) {
|
|
log.error({}, response.data.data.message);
|
|
return;
|
|
}
|
|
|
|
// update the release in the db leaving as insert just incase something weird happened
|
|
try {
|
|
await db
|
|
.insert(opendockApt)
|
|
.values({
|
|
release: release.ReleaseNumber,
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
})
|
|
.onConflictDoUpdate({
|
|
target: opendockApt.release,
|
|
set: {
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
upd_date: sql`NOW()`,
|
|
},
|
|
})
|
|
.returning();
|
|
|
|
log.info({}, `${release.ReleaseNumber} was updated`);
|
|
} catch (e) {
|
|
log.error(
|
|
{ stack: e },
|
|
`Error updating the release: ${release.ReleaseNumber}`,
|
|
);
|
|
}
|
|
// biome-ignore lint/suspicious/noExplicitAny: to many possibilities
|
|
} catch (e: any) {
|
|
//console.info(newDockApt);
|
|
log.error(
|
|
{ stack: e.response.data },
|
|
`An error has occurred during patching of the release: ${release.ReleaseNumber}`,
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
// set to inprogress
|
|
await delay(1500);
|
|
try {
|
|
const response = await axios.patch(
|
|
`${process.env.OPENDOCK_URL}/appointment/${id}`,
|
|
newDockApt,
|
|
{
|
|
headers: {
|
|
"content-type": "application/json; charset=utf-8",
|
|
Authorization: `Bearer ${odToken.odToken}`,
|
|
},
|
|
},
|
|
);
|
|
|
|
if (response.status === 400) {
|
|
log.error({}, response.data.data.message);
|
|
return;
|
|
}
|
|
|
|
// update the release in the db leaving as insert just incase something weird happened
|
|
try {
|
|
await db
|
|
.insert(opendockApt)
|
|
.values({
|
|
release: release.ReleaseNumber,
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
})
|
|
.onConflictDoUpdate({
|
|
target: opendockApt.release,
|
|
set: {
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
upd_date: sql`NOW()`,
|
|
},
|
|
})
|
|
.returning();
|
|
|
|
log.info({}, `${release.ReleaseNumber} was updated`);
|
|
} catch (e) {
|
|
log.error(
|
|
{ stack: e },
|
|
`Error updating the release: ${release.ReleaseNumber}`,
|
|
);
|
|
}
|
|
// biome-ignore lint/suspicious/noExplicitAny: to many possibilities
|
|
} catch (e: any) {
|
|
//console.info(newDockApt);
|
|
log.error(
|
|
{ stack: e.response.data },
|
|
`An error has occurred during patching of the release: ${release.ReleaseNumber}`,
|
|
);
|
|
|
|
return;
|
|
}
|
|
} else {
|
|
try {
|
|
const response = await axios.patch(
|
|
`${process.env.OPENDOCK_URL}/appointment/${id}`,
|
|
newDockApt,
|
|
{
|
|
headers: {
|
|
"content-type": "application/json; charset=utf-8",
|
|
Authorization: `Bearer ${odToken.odToken}`,
|
|
},
|
|
},
|
|
);
|
|
|
|
if (response.status === 400) {
|
|
log.error({}, response.data.data.message);
|
|
return;
|
|
}
|
|
|
|
// update the release in the db leaving as insert just incase something weird happened
|
|
try {
|
|
await db
|
|
.insert(opendockApt)
|
|
.values({
|
|
release: release.ReleaseNumber,
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
})
|
|
.onConflictDoUpdate({
|
|
target: opendockApt.release,
|
|
set: {
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
upd_date: sql`NOW()`,
|
|
},
|
|
})
|
|
.returning();
|
|
|
|
log.info({}, `${release.ReleaseNumber} was updated`);
|
|
} catch (e) {
|
|
log.error(
|
|
{ stack: e },
|
|
`Error updating the release: ${release.ReleaseNumber}`,
|
|
);
|
|
}
|
|
// biome-ignore lint/suspicious/noExplicitAny: to many possibilities
|
|
} catch (e: any) {
|
|
//console.info(newDockApt);
|
|
log.error(
|
|
{ stack: e.response.data },
|
|
`An error has occurred during patching of the release: ${release.ReleaseNumber}`,
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
} else if (opendDockArticleCheck?.loadType === "live") {
|
|
try {
|
|
const response = await axios.post(
|
|
`${process.env.OPENDOCK_URL}/appointment`,
|
|
newDockApt,
|
|
{
|
|
headers: {
|
|
"content-type": "application/json; charset=utf-8",
|
|
Authorization: `Bearer ${odToken.odToken}`,
|
|
},
|
|
},
|
|
);
|
|
|
|
// we need the id,release#,status from this response, store it in lst, check if we have a release so we can just update it.
|
|
// this will be utilized when we are listening for the changes to the apts. that way we can update the state to arrived. we will run our own checks on this guy during the incoming messages.
|
|
|
|
if (response.status === 400) {
|
|
log.error({}, response.data.data.message);
|
|
return;
|
|
}
|
|
|
|
// the response to make it simple we want response.data.id, response.data.relNumber, status will be defaulted to Scheduled if we created it here.
|
|
// TODO: add this release data to our db. but save it in json format and well parse it out. that way we future proof it and have everything in here vs just a few things
|
|
//console.info(response.data.data, "Was Created");
|
|
try {
|
|
await db
|
|
.insert(opendockApt)
|
|
.values({
|
|
release: release.ReleaseNumber,
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
})
|
|
.onConflictDoUpdate({
|
|
target: opendockApt.release,
|
|
set: {
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
upd_date: sql`NOW()`,
|
|
},
|
|
})
|
|
.returning();
|
|
|
|
log.info({}, `${release.ReleaseNumber} was created`);
|
|
} catch (e) {
|
|
log.error({ stack: e }, "Error creating new release");
|
|
}
|
|
// biome-ignore lint/suspicious/noExplicitAny: to many possibilities
|
|
} catch (e: any) {
|
|
log.error(
|
|
{ stack: e?.response?.data },
|
|
`Error posting new release to opendock, ${release.ReleaseNumber}`,
|
|
);
|
|
|
|
return;
|
|
}
|
|
} else if (
|
|
(releaseLoadtypeCheck ||
|
|
opendDockArticleCheck?.loadType === "drop" ||
|
|
defaultDock?.value === "drop") &&
|
|
releaseOkToSchedule
|
|
) {
|
|
try {
|
|
const response = await axios.post(
|
|
`${process.env.OPENDOCK_URL}/appointment`,
|
|
newDockApt,
|
|
{
|
|
headers: {
|
|
"content-type": "application/json; charset=utf-8",
|
|
Authorization: `Bearer ${odToken.odToken}`,
|
|
},
|
|
},
|
|
);
|
|
|
|
// we need the id,release#,status from this response, store it in lst, check if we have a release so we can just update it.
|
|
// this will be utilized when we are listening for the changes to the apts. that way we can update the state to arrived. we will run our own checks on this guy during the incoming messages.
|
|
|
|
if (response.status === 400) {
|
|
log.error({}, response.data.data.message);
|
|
return;
|
|
}
|
|
|
|
// the response to make it simple we want response.data.id, response.data.relNumber, status will be defaulted to Scheduled if we created it here.
|
|
// TODO: add this release data to our db. but save it in json format and well parse it out. that way we future proof it and have everything in here vs just a few things
|
|
//console.info(response.data.data, "Was Created");
|
|
try {
|
|
await db
|
|
.insert(opendockApt)
|
|
.values({
|
|
release: release.ReleaseNumber,
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
})
|
|
.onConflictDoUpdate({
|
|
target: opendockApt.release,
|
|
set: {
|
|
openDockAptId: response.data.data.id,
|
|
appointment: response.data.data,
|
|
upd_date: sql`NOW()`,
|
|
},
|
|
})
|
|
.returning();
|
|
|
|
log.info({}, `${release.ReleaseNumber} was created`);
|
|
} catch (e) {
|
|
log.error({ stack: e }, "Error creating new release");
|
|
}
|
|
// biome-ignore lint/suspicious/noExplicitAny: to many possibilities
|
|
} catch (e: any) {
|
|
log.error(
|
|
{ stack: e?.response?.data },
|
|
`Error posting new release to opendock, ${release.ReleaseNumber}`,
|
|
);
|
|
|
|
return;
|
|
}
|
|
} else {
|
|
// try {
|
|
// const response = await axios.post(
|
|
// `${process.env.OPENDOCK_URL}/appointment`,
|
|
// newDockApt,
|
|
// {
|
|
// headers: {
|
|
// "content-type": "application/json; charset=utf-8",
|
|
// Authorization: `Bearer ${odToken.odToken}`,
|
|
// },
|
|
// },
|
|
// );
|
|
|
|
// // we need the id,release#,status from this response, store it in lst, check if we have a release so we can just update it.
|
|
// // this will be utilized when we are listening for the changes to the apts. that way we can update the state to arrived. we will run our own checks on this guy during the incoming messages.
|
|
|
|
// if (response.status === 400) {
|
|
// log.error({}, response.data.data.message);
|
|
// return;
|
|
// }
|
|
|
|
// // the response to make it simple we want response.data.id, response.data.relNumber, status will be defaulted to Scheduled if we created it here.
|
|
// // TODO: add this release data to our db. but save it in json format and well parse it out. that way we future proof it and have everything in here vs just a few things
|
|
// //console.info(response.data.data, "Was Created");
|
|
// try {
|
|
// await db
|
|
// .insert(opendockApt)
|
|
// .values({
|
|
// release: release.ReleaseNumber,
|
|
// openDockAptId: response.data.data.id,
|
|
// appointment: response.data.data,
|
|
// })
|
|
// .onConflictDoUpdate({
|
|
// target: opendockApt.release,
|
|
// set: {
|
|
// openDockAptId: response.data.data.id,
|
|
// appointment: response.data.data,
|
|
// upd_date: sql`NOW()`,
|
|
// },
|
|
// })
|
|
// .returning();
|
|
|
|
// log.info({}, `${release.ReleaseNumber} was created`);
|
|
// } catch (e) {
|
|
// log.error({ stack: e }, "Error creating new release");
|
|
// }
|
|
// // biome-ignore lint/suspicious/noExplicitAny: to many possibilities
|
|
// } catch (e: any) {
|
|
// log.error(
|
|
// { stack: e?.response?.data },
|
|
// `Error posting new release to opendock, ${release.ReleaseNumber}`,
|
|
// );
|
|
|
|
// return;
|
|
// }
|
|
|
|
log.info(
|
|
{
|
|
stack: {
|
|
release: release.ReleaseNumber,
|
|
releaseLoadtypeCheck,
|
|
articleLoadType: opendDockArticleCheck?.loadType,
|
|
defaultLoadType: defaultDock?.value,
|
|
releaseOkToSchedule,
|
|
},
|
|
},
|
|
`Skipping OpenDock post - release: ${release.ReleaseNumber} is not allowed to schedule`,
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
await delay(750); // rate limit protection
|
|
};
|
|
|
|
export const monitorReleaseChanges = async () => {
|
|
// TODO: validate if the setting for opendocks is active and start / stop the system based on this
|
|
// if it changes we set to false and the next loop will stop.
|
|
|
|
const openDockMonitor = await db
|
|
.select()
|
|
.from(settings)
|
|
.where(eq(settings.name, "opendock_sync"));
|
|
// console.info("Starting release monitor", lastCheck);
|
|
|
|
const sqlQuery = sqlQuerySelector(`releaseChecks`) as SqlQuery;
|
|
|
|
if (!sqlQuery.success) {
|
|
return returnFunc({
|
|
success: false,
|
|
level: "error",
|
|
module: "datamart",
|
|
subModule: "query",
|
|
message: `Error getting releaseChecks info`,
|
|
data: [sqlQuery.message],
|
|
notify: false,
|
|
});
|
|
}
|
|
|
|
if (openDockMonitor[0]?.active) {
|
|
// const BUFFER_MS =
|
|
// Math.floor(parseInt(openDockMonitor[0]?.value, 10) || 30) * 1.5 * 1000; // this should be >= to the interval we set in the cron TODO: should pull the buffer from the setting and give it an extra 10% then round to nearest int.
|
|
|
|
createCronJob(
|
|
"opendock_sync",
|
|
`*/${parseInt(openDockMonitor[0]?.value, 10) || 30} * * * * *`,
|
|
async () => {
|
|
if (opendockSyncRunning) {
|
|
log.warn(
|
|
{},
|
|
"Skipping opendock_sync because previous run is still active",
|
|
);
|
|
return;
|
|
}
|
|
|
|
opendockSyncRunning = true;
|
|
try {
|
|
// set this to the latest time.
|
|
|
|
const result = await prodQuery(
|
|
sqlQuery.query.replace("[dateCheck]", `'${lastCheck}'`),
|
|
"Get release info",
|
|
);
|
|
|
|
log.debug(
|
|
{ lastCheck },
|
|
`${result.data.length} Changes to a release have been made`,
|
|
);
|
|
|
|
if (result.data.length) {
|
|
for (const release of result.data) {
|
|
await postRelease(release);
|
|
|
|
// add a 2 seconds to account for a massive influx of orders and when we dont finish in 1 go it wont try to grab the same amount again
|
|
const nDate = new Date(release.Upd_Date);
|
|
nDate.setSeconds(nDate.getSeconds() + 2);
|
|
|
|
lastCheck = formatInTimeZone(
|
|
nDate.toISOString(),
|
|
"UTC",
|
|
"yyyy-MM-dd HH:mm:ss",
|
|
);
|
|
log.debug({ lastCheck }, "Changes to a release have been made");
|
|
await delay(500);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error(
|
|
{ error: e },
|
|
"Error occurred while running the monitor job",
|
|
);
|
|
log.error(
|
|
{ error: e },
|
|
"Error occurred while running the monitor job",
|
|
);
|
|
} finally {
|
|
opendockSyncRunning = false;
|
|
}
|
|
},
|
|
"monitorReleaseChanges",
|
|
);
|
|
}
|
|
};
|