-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
notifications apres prise en charge svi
- Loading branch information
1 parent
383e20a
commit cb75663
Showing
16 changed files
with
332 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,47 @@ | ||
import * as Sentry from "@sentry/node"; | ||
import { ScopeContext } from "@sentry/types"; | ||
|
||
interface Context { | ||
extra?: Record<string, unknown>; | ||
[key: string]: unknown; | ||
} | ||
// Extend ScopeContext to make all properties optional | ||
interface OptionalScopeContext extends Partial<ScopeContext> {} | ||
|
||
type ErrorType = Error | string; | ||
export const capture = (err: Error, context: OptionalScopeContext = {}): void => { | ||
if (process.env.NODE_ENV === "development") { | ||
console.log("capture", err, context); | ||
} | ||
|
||
export function capture(err: ErrorType, context: Context | string): void { | ||
let parsedContext: Context; | ||
if (!context) { | ||
Sentry.captureException(err); | ||
return; | ||
} | ||
|
||
if (import.meta.env.DEV) { | ||
return console.log("capture", err, context); | ||
try { | ||
context = JSON.parse(JSON.stringify(context)); // deep copy context | ||
} catch (e) { | ||
console.error("Error parsing context", e); | ||
return; | ||
} | ||
if (typeof context === "string") { | ||
parsedContext = JSON.parse(context); | ||
} else { | ||
parsedContext = JSON.parse(JSON.stringify(context)); | ||
|
||
// @ts-expect-error Property 'status' does not exist on type 'unknown' | ||
if (context?.extra?.response?.status === 401) { | ||
return; | ||
} | ||
|
||
if (parsedContext.extra && typeof parsedContext.extra === "object") { | ||
try { | ||
const newExtra: Record<string, string> = {}; | ||
for (const [extraKey, extraValue] of Object.entries(parsedContext.extra)) { | ||
if (typeof extraValue === "string") { | ||
newExtra[extraKey] = extraValue; | ||
} else { | ||
const extraValueObj = extraValue as Record<string, unknown>; | ||
if (extraValueObj && "password" in extraValueObj) { | ||
extraValueObj.password = "******"; | ||
} | ||
newExtra[extraKey] = JSON.stringify(extraValueObj); | ||
} | ||
} | ||
parsedContext.extra = newExtra; | ||
} catch (e) { | ||
Sentry.captureMessage(String(e), parsedContext); | ||
if (context.extra) { | ||
const newExtra: Record<string, string> = {}; | ||
for (const extraKey of Object.keys(context.extra)) { | ||
newExtra[extraKey] = | ||
typeof context.extra[extraKey] === "string" ? context.extra[extraKey] : JSON.stringify(context.extra[extraKey]); | ||
} | ||
context.extra = newExtra; | ||
} | ||
|
||
if (typeof err === "string") { | ||
Sentry.captureMessage(err, parsedContext); | ||
if (Sentry && err) { | ||
if (typeof err === "string") { | ||
Sentry.captureMessage(err, context); | ||
} else { | ||
Sentry.captureException(err, context); | ||
} | ||
} else { | ||
Sentry.captureException(err, parsedContext); | ||
console.log("capture", err, JSON.stringify(context)); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// import feiEnfing from "./jobs/feiEnding"; | ||
// import { setupCronJob } from "./utils"; | ||
|
||
// await Promise.resolve().then( | ||
// async () => | ||
// await setupCronJob({ | ||
// name: "Pollens", | ||
// // There is no known rule for the update of the data. It is updated when the data is available. | ||
// // Data is valid from the day of issue until 7 days later | ||
// cronTime: "5 0/4 * * *", // every day starting at 00:05 every 4 hours | ||
// job: feiEnfing, | ||
// runOnInit: true, | ||
// }), | ||
// ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import * as cron from "cron"; | ||
import { capture } from "~/services/capture"; | ||
import { prisma } from "~/db/prisma.server"; | ||
import dayjs from "dayjs"; | ||
import utc from "dayjs/plugin/utc"; | ||
dayjs.extend(utc); | ||
/* | ||
* | ||
* | ||
Launch Cron Job function | ||
In order to prevent the same cron to be launched twice, we use a cronJob table in the database. | ||
If a cron is already running, we don't launch it again. | ||
*/ | ||
type TaskFn = () => Promise<void>; | ||
|
||
export async function launchCronJob(name: string, job: TaskFn): Promise<boolean> { | ||
try { | ||
const cronJobAlreadyExisting = await prisma.cronJob.findUnique({ | ||
where: { | ||
unique_key: `${dayjs().utc().format("YYYY-MM-DD:HH:mm")}_${name}`, | ||
}, | ||
}); | ||
if (cronJobAlreadyExisting) { | ||
capture(new Error(`Cron job ${name} already existing`), { | ||
level: "error", | ||
}); | ||
return false; | ||
} | ||
const cronJob = await prisma.cronJob.create({ | ||
data: { | ||
unique_key: `${dayjs().utc().format("YYYY-MM-DD:HH:mm")}_${name}`, | ||
name, | ||
active: true, | ||
}, | ||
}); | ||
|
||
await job(); | ||
|
||
await prisma.cronJob.update({ | ||
where: { | ||
id: cronJob.id, | ||
}, | ||
data: { | ||
active: false, | ||
}, | ||
}); | ||
return true; | ||
} catch (cronError: any) { | ||
capture(cronError, { level: "error", extra: { name } }); | ||
} | ||
return false; | ||
} | ||
|
||
/* | ||
* | ||
* | ||
Setpup Cron Job function | ||
Each cron job has the same parameters: | ||
- we launch it on init | ||
- we start it (all are activated) | ||
- we set the timezone to Europe/Paris | ||
*/ | ||
|
||
interface SetupCronJob { | ||
cronTime: string; | ||
name: string; | ||
job: TaskFn; | ||
runOnInit: boolean; | ||
} | ||
|
||
export async function setupCronJob({ cronTime, name, job, runOnInit = true }: SetupCronJob): Promise<boolean> { | ||
return await new Promise((resolve) => { | ||
cron.CronJob.from({ | ||
cronTime, | ||
onTick: async function () { | ||
const cronStarted = await launchCronJob(name, job); | ||
console.log(`${name}: next run at ${cron.sendAt(cronTime).toISO()}`); | ||
resolve(cronStarted); | ||
}, | ||
runOnInit, | ||
start: true, | ||
timeZone: "Europe/Paris", | ||
}); | ||
if (!runOnInit) { | ||
resolve(true); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
api-remix/prisma/migrations/20241023174019_svi_received_at/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
-- AlterTable | ||
ALTER TABLE "Fei" ADD COLUMN "svi_received_at" TIMESTAMP(3); | ||
|
||
-- CreateTable | ||
CREATE TABLE "CronJob" ( | ||
"id" TEXT NOT NULL, | ||
"unique_key" TEXT NOT NULL, | ||
"name" TEXT NOT NULL, | ||
"active" BOOLEAN NOT NULL DEFAULT true, | ||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
|
||
CONSTRAINT "CronJob_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "CronJob_unique_key_key" ON "CronJob"("unique_key"); |
9 changes: 9 additions & 0 deletions
9
api-remix/prisma/migrations/20241023174347_svi_assigned_at/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* | ||
Warnings: | ||
- You are about to drop the column `svi_received_at` on the `Fei` table. All the data in the column will be lost. | ||
*/ | ||
-- AlterTable | ||
ALTER TABLE "Fei" DROP COLUMN "svi_received_at", | ||
ADD COLUMN "svi_assigned_at" TIMESTAMP(3); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.