diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 10590123a1..6a08321304 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -111,6 +111,8 @@ "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "lint-staged": "14.0.1", + "ora": "8.1.1", + "postgres": "3.4.5", "prettier": "3.3.3", "puppeteer": "22.15.0", "strip-json-comments": "5.0.1", @@ -5878,6 +5880,19 @@ "node": ">=8" } }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-table3": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", @@ -8949,6 +8964,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -10101,6 +10129,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -13215,6 +13256,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", @@ -13731,6 +13785,202 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.1.tgz", + "integrity": "sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/ospath": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", @@ -14285,6 +14535,20 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/postgres": { + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.5.tgz", + "integrity": "sha512-cDWgoah1Gez9rN3H4165peY9qfpEo+SA61oQv65O3cRUE1pOEoJWwddwcqKE8XZYjbblOJlYDlLV4h67HrEVDg==", + "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -16118,6 +16382,19 @@ "node": ">=8" } }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/stream-events": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", diff --git a/frontend/package.json b/frontend/package.json index e95a30eccd..44ac88e31e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,6 +17,7 @@ "dev-puppeteer": "FRONTEND_OIDC_ENABLED=false FRONTEND_MONITORENV_URL=//localhost:9880 import-meta-env-prepare -u -x ./.env.local.defaults && vite --port 3000", "bundle-sw": "esbuild src/workers/serviceWorker.ts --bundle --outfile=public/service-worker.js", "prepare": "cd .. && ./frontend/node_modules/.bin/husky ./frontend/config/husky", + "generate:perfdata": "node ./scripts/generate_perf_data.js", "generate:testdata": "node ./scripts/generate_test_data_seeds.js", "start": "import-meta-env-prepare -u -x ./.env.local.defaults && vite preview --port 3000", "start:emulate": "npm run clean && npm run build && import-meta-env -x ./.env.example -p ./build/index.html && import-meta-env-prepare -u -x ./.env.local.defaults && vite preview --port 3000", @@ -136,6 +137,8 @@ "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "lint-staged": "14.0.1", + "ora": "8.1.1", + "postgres": "3.4.5", "prettier": "3.3.3", "puppeteer": "22.15.0", "strip-json-comments": "5.0.1", diff --git a/frontend/scripts/generate_perf_data.js b/frontend/scripts/generate_perf_data.js new file mode 100644 index 0000000000..d026426d2f --- /dev/null +++ b/frontend/scripts/generate_perf_data.js @@ -0,0 +1,280 @@ +/* eslint-disable no-await-in-loop */ + +import { faker } from '@faker-js/faker' +import dayjs from 'dayjs' +import ora from 'ora' +import postgres from 'postgres' + +const BATCH_SIZE = 1000 +const BATCH_SKELETON = new Array(BATCH_SIZE).fill(null) +const START_DATE = dayjs().subtract(6, 'months').toDate() +const END_DATE = dayjs().add(6, 'months').toDate() + +const FAKE_PNO_COUNT = 1000000 +const FAKE_PNO_BATCH_COUNT = FAKE_PNO_COUNT / BATCH_SIZE + +const FAKE_VESSEL_COUNT = 10000 +const FAKE_VESSEL_BATCH_COUNT = FAKE_VESSEL_COUNT / BATCH_SIZE + +const FAKE_REPORTING_COUNT = FAKE_VESSEL_COUNT * 3 +const FAKE_REPORTING_BATCH_COUNT = FAKE_REPORTING_COUNT / BATCH_SIZE + +function getFakePnoLogbookRawMessages(index) { + return [ + { + operation_number: `FAKE_OPERATION_${FAKE_PNO_COUNT + index}`, + xml_message: `Message FLUX xml` + }, + { + operation_number: `FAKE_OPERATION_${FAKE_PNO_COUNT + index}_RET`, + xml_message: `Message FLUX xml` + } + ] +} + +function getFakePnoLogbookReports(index) { + const vesselId = faker.number.int({ max: FAKE_VESSEL_COUNT * 2, min: FAKE_VESSEL_COUNT + 1 }) + const cfr = `FAKCFR_${vesselId}` + const vessel_name = `FAUX NAVIRE ${vesselId}` + + const tripStartDateAsDayjs = dayjs( + faker.date.between({ + from: START_DATE, + to: END_DATE + }) + ) + + const operation_datetime_utc = tripStartDateAsDayjs.add(26, 'hours').format('YYYY-MM-DD HH:mm:ss') + const report_id = `FAKE_OPERATION_${FAKE_PNO_COUNT + index}` + const transmission_format = 'ERS' + + return [ + { + cfr, + enriched: true, + flag_state: 'FRA', + id: FAKE_PNO_COUNT + index, + integration_datetime_utc: operation_datetime_utc, + log_type: 'PNO', + operation_datetime_utc, + operation_number: report_id, + operation_type: 'DAT', + referenced_report_id: null, + report_datetime_utc: operation_datetime_utc, + report_id, + transmission_format, + trip_gears: [ + { dimensions: '250;180', gear: 'TBN', mesh: 100 }, + { dimensions: '250;280', gear: 'OTT', mesh: 120.5 } + ], + trip_segments: [ + { segment: 'SWW04', segmentName: 'Chaluts pélagiques' }, + { segment: 'SWW06', segmentName: 'Sennes' } + ], + value: { + authorTrigram: null, + catchOnboard: [ + { + economicZone: 'FRA', + effortZone: 'C', + faoZone: '27.8.a', + nbFish: null, + species: 'ANF', + statisticalRectangle: '23E6', + weight: 150 + } + ], + pnoTypes: [ + { + hasDesignatedPorts: false, + minimumNotificationPeriod: 4, + pnoTypeName: 'Préavis type Z' + } + ], + port: 'BROIA', + predictedArrivalDatetimeUtc: tripStartDateAsDayjs.add(30, 'hours').format('YYYY-MM-DDTHH:mm:ss[Z]'), + predictedLandingDatetimeUtc: tripStartDateAsDayjs.add(31, 'hours').format('YYYY-MM-DDTHH:mm:ss[Z]'), + purpose: 'LAN', + riskFactor: 2.9, + tripStartDate: tripStartDateAsDayjs.format('YYYY-MM-DDTHH:mm:ss[Z]'), + updatedAt: null, + updatedBy: null + }, + vessel_name + }, + // We need to have the exact same props as the DAT report otherwise `sql()` batch insert will fail + { + cfr: null, + enriched: true, + flag_state: null, + id: 2 * FAKE_PNO_COUNT + index, + integration_datetime_utc: operation_datetime_utc, + log_type: null, + operation_datetime_utc, + operation_number: `${report_id}_RET`, + operation_type: 'RET', + referenced_report_id: report_id, + report_datetime_utc: null, + report_id: null, + transmission_format, + trip_gears: null, + trip_segments: null, + value: { + returnStatus: '000' + }, + vessel_name: null + } + ] +} + +function getFakeReporting(index) { + const vessel_id = faker.number.int({ max: FAKE_VESSEL_COUNT * 2, min: FAKE_VESSEL_COUNT + 1 }) + const internal_reference_number = `FAKCFR_${vessel_id}` + const vessel_name = `FAUX NAVIRE ${vessel_id}` + + const creationDate = dayjs( + faker.date.between({ + from: START_DATE, + to: END_DATE + }) + ) + + const type = faker.helpers.arrayElement(['ALERT', 'INFRACTION_SUSPICION', 'OBSERVATION']) + const value = + type === 'ALERT' + ? { + natinfCode: 7059, + riskFactor: faker.number.float({ max: 5, min: 0 }), + seaFront: faker.helpers.arrayElement(['MED', 'MEMN', 'NAMO', 'SA']), + type: 'THREE_MILES_TRAWLING_ALERT' + } + : { + authorContact: '', + authorTrigram: faker.string.alpha(3).toUpperCase(), + controlUnitId: null, + description: faker.lorem.sentence(), + dml: 'DML 29', + natinfCode: 23588, + reportingActor: faker.helpers.arrayElement(['OPS', 'UNIT']), + seaFront: faker.helpers.arrayElement(['MED', 'MEMN', 'NAMO', 'SA']), + title: faker.lorem.sentence(), + type + } + + return { + archived: false, + creation_date: creationDate.format('YYYY-MM-DD HH:mm:ss'), + deleted: false, + external_reference_number: null, + flag_state: 'FR', + id: FAKE_REPORTING_COUNT + index, + internal_reference_number, + ircs: null, + latitude: faker.location.latitude({ max: 51, min: 42, precision: 3 }), + longitude: faker.location.longitude({ max: 10, min: -7, precision: 3 }), + type, + validation_date: creationDate.add(2, 'hours').format('YYYY-MM-DD HH:mm:ss'), + value, + vessel_id, + vessel_identifier: 'INTERNAL_REFERENCE_NUMBER', + vessel_name + } +} + +function getFakeVessel(index) { + const id = FAKE_VESSEL_COUNT + index + + return { + cfr: `FAKCFR_${id}`, + flag_state: 'FR', + id, + length: 99, + vessel_name: `FAUX NAVIRE ${id}` + } +} + +const sql = postgres('postgres://postgres:postgres@localhost:5432/monitorfishdb') + +async function run() { + let batchIndex + const spinner = ora('Starting...').start() + + try { + // Ignore SQL notices + await sql`SET client_min_messages TO WARNING` + + spinner.text = 'Deleting fake vessels...' + await sql`DELETE FROM vessels WHERE id >= ${FAKE_VESSEL_COUNT + 1} AND id <= ${FAKE_VESSEL_COUNT * 2}` + spinner.succeed('Fake vessels successfully deleted.') + + spinner.start('Generating fake vessels...') + batchIndex = 1 + while (batchIndex <= FAKE_VESSEL_BATCH_COUNT) { + const startIndex = (batchIndex - 1) * BATCH_SIZE + 1 + const endIndex = batchIndex * BATCH_SIZE + spinner.text = `Generating fake vessels ${startIndex}->${endIndex} / ${FAKE_VESSEL_COUNT} (${Math.round((10000 * startIndex) / FAKE_VESSEL_COUNT) / 100}%)...` + + const fakeVessels = BATCH_SKELETON.map((_, index) => getFakeVessel(startIndex + index)) + await sql`INSERT INTO vessels ${sql(fakeVessels)}` + + batchIndex += 1 + } + spinner.succeed('Fake vessels successfully generated.') + + spinner.start('Deleting fake reportings...') + await sql`DELETE FROM reportings WHERE id >= ${FAKE_REPORTING_COUNT + 1} AND id <= ${FAKE_REPORTING_COUNT * 2}` + spinner.succeed('Fake reportings successfully deleted.') + + spinner.start('Generating fake reporting...') + batchIndex = 1 + while (batchIndex <= FAKE_REPORTING_BATCH_COUNT) { + const startIndex = (batchIndex - 1) * BATCH_SIZE + 1 + const endIndex = batchIndex * BATCH_SIZE + spinner.text = `Generating fake reportings ${startIndex}->${endIndex} / ${FAKE_REPORTING_COUNT} (${Math.round((10000 * startIndex) / FAKE_REPORTING_COUNT) / 100}%)...` + + const fakeReportings = BATCH_SKELETON.map((_, index) => getFakeReporting(startIndex + index)) + await sql`INSERT INTO reportings ${sql(fakeReportings)}` + + batchIndex += 1 + } + spinner.succeed('Fake reportings successfully generated.') + + spinner.start('Deleting fake PNO logbook reports...') + // Prevent TimescaleDB truncate cascade notices from spamming output (`truncate cascades to table "_hyper_2_135_chunk"`) + await sql`SET client_min_messages TO WARNING` + await sql`TRUNCATE TABLE logbook_raw_messages CASCADE` + await sql`TRUNCATE TABLE logbook_reports` + await sql`RESET client_min_messages` + spinner.succeed('Fake PNO logbook reports successfully deleted.') + + spinner.start('Generating fake PNO logbook report...') + batchIndex = 1 + while (batchIndex <= FAKE_PNO_BATCH_COUNT) { + const startIndex = (batchIndex - 1) * BATCH_SIZE + 1 + const endIndex = batchIndex * BATCH_SIZE + spinner.text = `Generating fake PNO logbook report ${startIndex}->${endIndex} / ${FAKE_PNO_COUNT} (${Math.round((10000 * startIndex) / FAKE_PNO_COUNT) / 100}%)...` + + const fakeLogbookRawMessages = BATCH_SKELETON.flatMap((_, index) => + getFakePnoLogbookRawMessages(startIndex + index) + ) + const fakeLogbookReports = BATCH_SKELETON.flatMap((_, index) => getFakePnoLogbookReports(startIndex + index)) + + spinner.text = `Generating fake PNO logbook report ${startIndex}->${endIndex} / ${FAKE_PNO_COUNT} (${Math.round((10000 * startIndex) / FAKE_PNO_COUNT) / 100}%) [RANDOMNESS CHECK: ${fakeLogbookReports[0].operation_datetime_utc}]...` + await sql`INSERT INTO logbook_raw_messages ${sql(fakeLogbookRawMessages)}` + await sql`INSERT INTO logbook_reports ${sql(fakeLogbookReports)}` + + batchIndex += 1 + } + spinner.succeed('Fake PNO logbook report successfully generated.') + } catch (error) { + spinner.fail('Failed to generate perf data.') + + console.error(error) + + process.exit(1) + } finally { + await sql.end() + } +} + +run() diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx index 19b6789fc5..efa368874f 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx @@ -75,7 +75,9 @@ export function PriorNotificationList({ isFromUrl }: PriorNotificationListProps) } // `!!error` !== `isError` because `isError` is `false` when the query is fetching. const { data, error, isError, isFetching } = useGetPriorNotificationsQuery(rtkQueryParams, { - ...RTK_ONE_MINUTE_POLLING_QUERY_OPTIONS, + pollingInterval: 3000, + refetchOnMountOrArgChange: true, + refetchOnReconnect: true, ...RTK_FORCE_REFETCH_QUERY_OPTIONS }) useHandleFrontendApiError(