From 8113aea0c65fb1b13db26fb926ce2861dd41f24a Mon Sep 17 00:00:00 2001 From: Laura Bergoens Date: Tue, 5 Nov 2024 15:05:52 +0100 Subject: [PATCH 1/3] Setup ecosystem before starting server to avoid latencies Co-authored-by: Nicolas Lepage Co-authored-by: Emmanuel Feller Co-authored-by: Diane Cordier Co-authored-by: Guillaume Lagorce --- api/db/knex-database-connection.js | 7 ++++++- api/index.js | 19 ++++++++++++++++++- .../learning-content/datasource.js | 4 +++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/api/db/knex-database-connection.js b/api/db/knex-database-connection.js index cdbc27c4936..0e742a84b7e 100644 --- a/api/db/knex-database-connection.js +++ b/api/db/knex-database-connection.js @@ -118,4 +118,9 @@ async function emptyAllTables() { return configuredKnex.raw(`${query}${tables}`); } -export { disconnect, emptyAllTables, configuredKnex as knex }; +async function prepareDatabaseConnection() { + await configuredKnex.raw('SELECT 1'); + logger.info('Connection to database established.'); +} + +export { disconnect, emptyAllTables, configuredKnex as knex, prepareDatabaseConnection }; diff --git a/api/index.js b/api/index.js index 7f65e8a7e73..88df9a7a05a 100644 --- a/api/index.js +++ b/api/index.js @@ -4,16 +4,33 @@ import { validateEnvironmentVariables } from './src/shared/infrastructure/valida validateEnvironmentVariables(); -import { disconnect } from './db/knex-database-connection.js'; +import { disconnect, prepareDatabaseConnection } from './db/knex-database-connection.js'; import { createServer } from './server.js'; import { learningContentCache } from './src/shared/infrastructure/caches/learning-content-cache.js'; +import { initLearningContent } from './src/shared/infrastructure/datasources/learning-content/datasource.js'; import { temporaryStorage } from './src/shared/infrastructure/temporary-storage/index.js'; import { logger } from './src/shared/infrastructure/utils/logger.js'; import { redisMonitor } from './src/shared/infrastructure/utils/redis-monitor.js'; let server; +async function _setupEcosystem() { + /* + Load learning content from Redis to memory cache can take some time + Hence, we force this loading before the server starts so the requests can + immediately be responded. + */ + await initLearningContent(); + /* + First connection with Knex requires infrastructure operations such as + DNS resolution. So we execute one harmless query to our database + so those matters are resolved before starting the server. + */ + await prepareDatabaseConnection(); +} + const start = async function () { + await _setupEcosystem(); server = await createServer(); await server.start(); }; diff --git a/api/src/shared/infrastructure/datasources/learning-content/datasource.js b/api/src/shared/infrastructure/datasources/learning-content/datasource.js index c79a217e158..b183cde9f7e 100644 --- a/api/src/shared/infrastructure/datasources/learning-content/datasource.js +++ b/api/src/shared/infrastructure/datasources/learning-content/datasource.js @@ -77,4 +77,6 @@ const refreshLearningContentCacheRecords = async function () { return learningContent; }; -export { extend, refreshLearningContentCacheRecords }; +const initLearningContent = _DatasourcePrototype._getLearningContent; + +export { extend, initLearningContent, refreshLearningContentCacheRecords }; From 598547a85b0e4293f9bc6998520c67eab6aa9fcf Mon Sep 17 00:00:00 2001 From: Emmanuel FELLER Date: Wed, 6 Nov 2024 12:14:58 +0100 Subject: [PATCH 2/3] Add feature toggle to be able to disable ecosystem pre-loading before start --- api/index.js | 5 ++++- api/src/shared/config.js | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/api/index.js b/api/index.js index 88df9a7a05a..585ade7a730 100644 --- a/api/index.js +++ b/api/index.js @@ -6,6 +6,7 @@ validateEnvironmentVariables(); import { disconnect, prepareDatabaseConnection } from './db/knex-database-connection.js'; import { createServer } from './server.js'; +import { config } from './src/shared/config.js'; import { learningContentCache } from './src/shared/infrastructure/caches/learning-content-cache.js'; import { initLearningContent } from './src/shared/infrastructure/datasources/learning-content/datasource.js'; import { temporaryStorage } from './src/shared/infrastructure/temporary-storage/index.js'; @@ -30,7 +31,9 @@ async function _setupEcosystem() { } const start = async function () { - await _setupEcosystem(); + if (config.featureToggles.setupEcosystemBeforeStart) { + await _setupEcosystem(); + } server = await createServer(); await server.start(); }; diff --git a/api/src/shared/config.js b/api/src/shared/config.js index ea920b76eba..e5bd834bb54 100644 --- a/api/src/shared/config.js +++ b/api/src/shared/config.js @@ -214,6 +214,7 @@ const configuration = (function () { isQuestEnabled: toBoolean(process.env.FT_ENABLE_QUESTS), isTextToSpeechButtonEnabled: toBoolean(process.env.FT_ENABLE_TEXT_TO_SPEECH_BUTTON), isV3EligibilityCheckEnabled: toBoolean(process.env.FT_ENABLE_V3_ELIGIBILITY_CHECK), + setupEcosystemBeforeStart: toBoolean(process.env.FT_SETUP_ECOSYSTEM_BEFORE_START) || false, showExperimentalMissions: toBoolean(process.env.FT_SHOW_EXPERIMENTAL_MISSIONS), showNewCampaignPresentationPage: toBoolean(process.env.FT_SHOW_NEW_CAMPAIGN_PRESENTATION_PAGE), showNewResultPage: toBoolean(process.env.FT_SHOW_NEW_RESULT_PAGE), From c6bf01eea32cc4057119b77af09ab3e358cde15a Mon Sep 17 00:00:00 2001 From: Emmanuel FELLER Date: Wed, 6 Nov 2024 14:44:49 +0100 Subject: [PATCH 3/3] fix acceptance test --- .../feature-toggles/feature-toggle-controller_test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/api/tests/shared/acceptance/application/feature-toggles/feature-toggle-controller_test.js b/api/tests/shared/acceptance/application/feature-toggles/feature-toggle-controller_test.js index c76f071564f..bb99828175a 100644 --- a/api/tests/shared/acceptance/application/feature-toggles/feature-toggle-controller_test.js +++ b/api/tests/shared/acceptance/application/feature-toggles/feature-toggle-controller_test.js @@ -32,6 +32,7 @@ describe('Acceptance | Shared | Application | Controller | feature-toggle', func 'is-self-account-deletion-enabled': false, 'is-text-to-speech-button-enabled': false, 'is-v3-eligibility-check-enabled': false, + 'setup-ecosystem-before-start': false, 'show-experimental-missions': false, 'show-new-campaign-presentation-page': false, 'show-new-result-page': false,