diff --git a/article/app/AppLoader.scala b/article/app/AppLoader.scala index c85eea8f120e..b2e6c3e23fac 100644 --- a/article/app/AppLoader.scala +++ b/article/app/AppLoader.scala @@ -5,6 +5,7 @@ import com.softwaremill.macwire._ import common.Assets.DiscussionExternalAssetsLifecycle import common._ import common.dfp.DfpAgentLifecycle +import common.commercial.CommercialBundleUrlLifecycle import concurrent.BlockingOperations import conf.{CachedHealthCheckLifeCycle, Configuration} import conf.switches.SwitchboardLifecycle @@ -46,6 +47,7 @@ trait AppComponents extends FrontendComponents with ArticleControllers { override lazy val lifecycleComponents = List( wire[NewspaperBooksAndSectionsAutoRefresh], wire[DfpAgentLifecycle], + wire[CommercialBundleUrlLifecycle], wire[CloudWatchMetricsLifecycle], wire[SurgingContentAgentLifecycle], wire[SwitchboardLifecycle], diff --git a/commercial/app/AppLoader.scala b/commercial/app/AppLoader.scala index 994dcd796627..d283d87c2756 100644 --- a/commercial/app/AppLoader.scala +++ b/commercial/app/AppLoader.scala @@ -9,6 +9,7 @@ import commercial.model.merchandise.jobs.{Industries, JobsAgent} import commercial.model.merchandise.travel.TravelOffersAgent import common.CloudWatchMetricsLifecycle import common.dfp.DfpAgentLifecycle +import common.commercial.CommercialBundleUrlLifecycle import conf.switches.SwitchboardLifecycle import conf.CachedHealthCheckLifeCycle import contentapi.{CapiHttpClient, ContentApiClient, HttpClient} @@ -55,6 +56,7 @@ trait AppComponents extends FrontendComponents with CommercialControllers with C override lazy val lifecycleComponents = List( wire[CommercialLifecycle], wire[DfpAgentLifecycle], + wire[CommercialBundleUrlLifecycle], wire[SwitchboardLifecycle], wire[CloudWatchMetricsLifecycle], wire[CachedHealthCheckLifeCycle], diff --git a/common/app/common/commercial/CommercialBundleUrlAgent.scala b/common/app/common/commercial/CommercialBundleUrlAgent.scala new file mode 100644 index 000000000000..f36df3713ba9 --- /dev/null +++ b/common/app/common/commercial/CommercialBundleUrlAgent.scala @@ -0,0 +1,44 @@ +package common.commercial + +import conf.Configuration.commercial._ +import services.S3 +import play.api.libs.json.Json +import common.GuLogging + +case class AssetMap( + commercialStandalone: Option[String], +) + +object AssetMapParser { + def apply(assetMap: String): Option[AssetMap] = { + val assetMapJson = Json.parse(assetMap) + Some( + AssetMap( + (assetMapJson \ "commercial-standalone.js").asOpt[String], + ), + ) + } +} + +object CommercialBundleUrlAgent extends GuLogging { + + var bundlePath: String = getBundlePath() + + def getAssetMap(): AssetMap = { + S3.get(commercialAssetMap) flatMap (AssetMapParser( + _, + )) getOrElse AssetMap(None) + } + + def getBundlePath(): String = { + getAssetMap().commercialStandalone match { + case Some(p) => "test_commercial_bundles/" + p + case None => "javascripts/commercial/graun.standalone.commercial.js" + } + } + + def refresh(): Unit = { + bundlePath = getBundlePath() + log.logger.info(s"Commercial bundle path is now $bundlePath") + } +} diff --git a/common/app/common/commercial/CommercialBundleUrlLifecycle.scala b/common/app/common/commercial/CommercialBundleUrlLifecycle.scala new file mode 100644 index 000000000000..118b26dc880c --- /dev/null +++ b/common/app/common/commercial/CommercialBundleUrlLifecycle.scala @@ -0,0 +1,32 @@ +package common.commercial + +import app.LifecycleComponent +import common.{JobScheduler, PekkoAsync} +import play.api.inject.ApplicationLifecycle + +import scala.concurrent.{ExecutionContext, Future} + +class CommercialBundleUrlLifecycle(appLifeCycle: ApplicationLifecycle, jobs: JobScheduler, pekkoAsync: PekkoAsync)( + implicit ec: ExecutionContext, +) extends LifecycleComponent { + + appLifeCycle.addStopHook { () => + Future { + jobs.deschedule("CommercialBundleUrlRefreshJob") + } + } + + def refreshCommercialBundleUrl(): Unit = CommercialBundleUrlAgent.refresh() + + override def start(): Unit = { + jobs.deschedule("CommercialBundleUrlRefreshJob") + jobs.scheduleEveryNMinutes("CommercialBundleUrlRefreshJob", 1) { + refreshCommercialBundleUrl() + Future.successful(()) + } + + pekkoAsync.after1s { + refreshCommercialBundleUrl() + } + } +} diff --git a/common/app/common/configuration.scala b/common/app/common/configuration.scala index ac9a0b22e637..1b883c565904 100644 --- a/common/app/common/configuration.scala +++ b/common/app/common/configuration.scala @@ -12,10 +12,12 @@ import common.Environment.{app, awsRegion, stage} import conf.{Configuration, Static} import org.apache.commons.io.IOUtils import services.ParameterStore +import model.dotcomrendering.DotcomRenderingUtils.assetURL import scala.jdk.CollectionConverters._ import scala.concurrent.duration._ import scala.util.{Failure, Success, Try} +import common.commercial.CommercialBundleUrlAgent class BadConfigurationException(msg: String) extends RuntimeException(msg) @@ -524,9 +526,8 @@ class GuardianConfiguration extends GuLogging { lazy val prebidServerUrl = configuration.getStringProperty("commercial.prebid.server.url") getOrElse "http://localhost:8000" - lazy val overrideCommercialBundleUrl: Option[String] = - if (environment.isDev) configuration.getStringProperty("commercial.overrideCommercialBundleUrl") - else None + lazy val commercialAssetMap = s"$commercialRoot/assets-map/assets.map" + lazy val commercialBundleUrl = assetURL(CommercialBundleUrlAgent.bundlePath) } object journalism { diff --git a/common/app/views/support/JavaScriptPage.scala b/common/app/views/support/JavaScriptPage.scala index a78f2d6c18c0..745eb30722f7 100644 --- a/common/app/views/support/JavaScriptPage.scala +++ b/common/app/views/support/JavaScriptPage.scala @@ -71,8 +71,7 @@ object JavaScriptPage { val ipsos = if (page.metadata.isFront) getScriptTag(page.metadata.id) else getScriptTag(page.metadata.sectionId) val commercialBundleUrl = JsString( - Configuration.commercial.overrideCommercialBundleUrl - .getOrElse(assetURL("javascripts/commercial/graun.standalone.commercial.js")), + Configuration.commercial.commercialBundleUrl, ) javascriptConfig ++ config ++ commercialMetaData ++ journalismMetaData ++ Map( diff --git a/dev-build/app/AppLoader.scala b/dev-build/app/AppLoader.scala index 17e5c9bee7ef..838c622fc54e 100644 --- a/dev-build/app/AppLoader.scala +++ b/dev-build/app/AppLoader.scala @@ -17,6 +17,7 @@ import cricket.conf.CricketLifecycle import cricket.controllers.CricketControllers import dev.DevAssetsController import dfp.DfpDataCacheLifecycle +import common.commercial.CommercialBundleUrlLifecycle import feed._ import football.controllers._ import http.{CorsHttpErrorHandler, DevBuildParametersHttpRequestHandler, DevFilters} @@ -91,6 +92,7 @@ trait AppComponents wire[OnwardJourneyLifecycle], wire[CommercialLifecycle], wire[DfpDataCacheLifecycle], + wire[CommercialBundleUrlLifecycle], wire[FaciaDfpAgentLifecycle], wire[ConfigAgentLifecycle], wire[SurgingContentAgentLifecycle], diff --git a/facia/app/AppLoader.scala b/facia/app/AppLoader.scala index e1677a9c5c29..d6bdad168182 100644 --- a/facia/app/AppLoader.scala +++ b/facia/app/AppLoader.scala @@ -4,6 +4,7 @@ import app.{FrontendApplicationLoader, FrontendBuildInfo, FrontendComponents} import com.softwaremill.macwire._ import common._ import common.dfp.FaciaDfpAgentLifecycle +import common.commercial.CommercialBundleUrlLifecycle import concurrent.BlockingOperations import conf.switches.SwitchboardLifecycle import conf.CachedHealthCheckLifeCycle @@ -54,6 +55,7 @@ trait AppComponents extends FrontendComponents with FaciaControllers with FapiSe wire[ConfigAgentLifecycle], wire[CloudWatchMetricsLifecycle], wire[FaciaDfpAgentLifecycle], + wire[CommercialBundleUrlLifecycle], wire[SurgingContentAgentLifecycle], wire[IndexListingsLifecycle], wire[SwitchboardLifecycle], diff --git a/preview/app/AppLoader.scala b/preview/app/AppLoader.scala index 73b9df1b38c5..3da928ee52fb 100644 --- a/preview/app/AppLoader.scala +++ b/preview/app/AppLoader.scala @@ -8,6 +8,7 @@ import commercial.CommercialLifecycle import commercial.controllers.CommercialControllers import commercial.targeting.TargetingLifecycle import common.dfp.FaciaDfpAgentLifecycle +import common.commercial.CommercialBundleUrlLifecycle import common.{ApplicationMetrics, CloudWatchMetricsLifecycle, ContentApiMetrics, DCRMetrics} import conf.switches.SwitchboardLifecycle import conf.{CachedHealthCheckLifeCycle, FootballLifecycle} @@ -53,6 +54,7 @@ trait PreviewLifecycleComponents wire[OnwardJourneyLifecycle], wire[ConfigAgentLifecycle], wire[FaciaDfpAgentLifecycle], + wire[CommercialBundleUrlLifecycle], wire[SwitchboardLifecycle], wire[FootballLifecycle], wire[CricketLifecycle],