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..585ade7a730 100644 --- a/api/index.js +++ b/api/index.js @@ -4,16 +4,36 @@ 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 { 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'; 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 () { + 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), 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 }; 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,