From 7d46d5739be2863b705689d43ab377fa89e9eead Mon Sep 17 00:00:00 2001 From: Eric Boucher Date: Fri, 10 Nov 2023 13:07:03 +0100 Subject: [PATCH] Fix alerts daily job (#950) --- .github/workflows/alerting.yml | 18 +++++------- LICENSE | 2 +- alerting/Dockerfile | 2 +- alerting/package.json | 1 + alerting/src/alert-worker.ts | 41 ++++++++++++++++++++++------ alerting/src/utils/analysis-utils.ts | 7 +++++ alerting/tsconfig.json | 2 +- alerting/yarn.lock | 17 ++++++++---- 8 files changed, 61 insertions(+), 29 deletions(-) diff --git a/.github/workflows/alerting.yml b/.github/workflows/alerting.yml index 9f070c7c9..baf9d6dd0 100644 --- a/.github/workflows/alerting.yml +++ b/.github/workflows/alerting.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: PRISM Alerts on: @@ -18,12 +16,8 @@ jobs: runs-on: ubuntu-latest env: - POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} - POSTGRES_PORT: 54321 - POSTGRES_USER: postgres - POSTGRES_DB: postgres - DATABASE_URL: ${{ secrets.DATABASE_URL }} - EMAIL_PASSWORD: ${{ secrets.EMAIL_PASSWORD }} + PRISM_ALERTS_DATABASE_URL: ${{ secrets.PRISM_ALERTS_DATABASE_URL }} + EMAIL_PASSWORD: ${{ secrets.PRISM_ALERTS_EMAIL_PASSWORD }} # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it steps: @@ -33,6 +27,8 @@ jobs: node-version: '16' # Run alert worker - - run: cd alerting - - run: yarn - - run: ts-node src/alert-worker.ts + - run: | + cd alerting + yarn install + yarn setup:common + yarn alert-worker diff --git a/LICENSE b/LICENSE index ae88b866e..2f46160a5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 World Food Programme +Copyright (c) 2023 World Food Programme Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/alerting/Dockerfile b/alerting/Dockerfile index 1f7d57047..1d16ea8fa 100644 --- a/alerting/Dockerfile +++ b/alerting/Dockerfile @@ -1,4 +1,4 @@ -FROM node:12 +FROM node:16 COPY ./alerting /app diff --git a/alerting/package.json b/alerting/package.json index 1f9916b8e..59591bc20 100644 --- a/alerting/package.json +++ b/alerting/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@turf/bbox": "^6.3.0", + "bluebird": "^3.7.2", "geojson": "^0.5.0", "lodash": "^4.17.21", "moment": "^2.29.4", diff --git a/alerting/src/alert-worker.ts b/alerting/src/alert-worker.ts index 389b3f58b..f236f626f 100644 --- a/alerting/src/alert-worker.ts +++ b/alerting/src/alert-worker.ts @@ -1,4 +1,6 @@ import { isNaN } from 'lodash'; +import Bluebird from 'bluebird'; +import nodeFetch from 'node-fetch'; import { createConnection, Repository } from 'typeorm'; import { ANALYSIS_API_URL } from './constants'; import { Alert } from './entities/alerts.entity'; @@ -6,6 +8,8 @@ import { calculateBoundsForAlert } from './utils/analysis-utils'; import { sendEmail } from './utils/email'; import { fetchCoverageLayerDays, formatUrl, WMS } from 'prism-common'; +// @ts-ignore +global.fetch = nodeFetch; async function processAlert(alert: Alert, alertRepository: Repository) { const { @@ -24,15 +28,26 @@ async function processAlert(alert: Alert, alertRepository: Repository) { prismUrl, active, } = alert; - const availableDates = - type === 'wms' - ? await new WMS(`${baseUrl}/wms`).getLayerDays() + + let availableDates; + let layerAvailableDates = []; + try { + availableDates = type === 'wms' + ? await new WMS(`${baseUrl}/wms`.replace(/([^:]\/)\/+/g, "$1")).getLayerDays() : await fetchCoverageLayerDays(baseUrl); - const layerAvailableDates = availableDates[serverLayerName]; + layerAvailableDates = availableDates[serverLayerName]; + } catch (error) { + console.warn(`Failed to fetch available dates for ${baseUrl} ${serverLayerName}: ${(error as Error).message}`); + } + + if (!layerAvailableDates) { + console.warn(`No dates available for ${baseUrl} ${serverLayerName}.`); + return; + } + const maxDate = new Date(Math.max(...(layerAvailableDates || []))); if ( - !active || isNaN(maxDate.getTime()) || (lastTriggered && lastTriggered >= maxDate) || createdAt >= maxDate @@ -91,11 +106,19 @@ async function run() { const connection = await createConnection(); const alertRepository = connection.getRepository(Alert); - const alerts = await alertRepository.find(); - console.info(`Processing ${alerts.length} alerts.`); + const alerts = await alertRepository.find({ where: { active: true } }); + console.info(`Processing ${alerts.length} active alerts.`); - await Promise.all( - alerts.map(async (alert) => processAlert(alert, alertRepository)), + await Bluebird.map( + alerts, + async (alert) => { + try { + await processAlert(alert, alertRepository); + } catch (error) { + console.error(`Error processing alert ${alert.id}:`, error); + } + }, + { concurrency: 5 }, ); } diff --git a/alerting/src/utils/analysis-utils.ts b/alerting/src/utils/analysis-utils.ts index 2b4da97e6..a80243873 100644 --- a/alerting/src/utils/analysis-utils.ts +++ b/alerting/src/utils/analysis-utils.ts @@ -66,6 +66,13 @@ export function getAlertMessage( let alertMessage; + // test if aggregateData is an array + if (!Array.isArray(aggregateData)) { + console.warn('aggregateData is not an array'); + console.warn('aggregateData', JSON.stringify(aggregateData)); + return undefined + } + aggregateData.forEach((data) => { const minValue = scaleValueIfDefined( get(data, 'stats_min') as number, diff --git a/alerting/tsconfig.json b/alerting/tsconfig.json index f919995d1..ddde2f9e3 100644 --- a/alerting/tsconfig.json +++ b/alerting/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "noEmit": true, "emitDecoratorMetadata": true, "module": "commonjs", "target": "es5", @@ -14,7 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true, "jsx": "react", "strictPropertyInitialization": false, "experimentalDecorators": true, diff --git a/alerting/yarn.lock b/alerting/yarn.lock index 2aabc21ec..955a20419 100644 --- a/alerting/yarn.lock +++ b/alerting/yarn.lock @@ -1089,6 +1089,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2604,9 +2609,9 @@ natural-compare@^1.4.0: integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -3345,7 +3350,7 @@ tr46@^2.1.0: tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-jest@^24.0: version "24.3.0" @@ -3526,7 +3531,7 @@ wcwidth@^1.0.1: webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== webidl-conversions@^5.0.0: version "5.0.0" @@ -3553,7 +3558,7 @@ whatwg-mimetype@^2.3.0: whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0"