Class HomeStatsRefresher

java.lang.Object
ubic.gemma.core.analysis.report.HomeStatsRefresher

@Component public class HomeStatsRefresher extends Object
Refreshes HomeStats on a daily cron AND on every Spring context refresh (startup). The two triggers use different Spring mechanisms on purpose:

Startup pass rides on ContextRefreshedEvent so it fires in every server context — REST, dev, scheduler — regardless of whether @EnableScheduling is active (it is skipped under the EnvironmentProfiles.CLI profile, which has no homepage to warm). @Scheduled now fires on production nodes too (see AnnotationDrivenSchedulingConfig), but not under dev or test, so the lifecycle event remains the only trigger there. It runs the refresh in a background thread so Spring startup isn't blocked by the minute-or-two cold-cache aggregation pass.

Daily cron stays on Scheduled. It only fires on nodes with the scheduler profile active (which is what we want — daily refresh is a single-node responsibility on the production scheduler). The cron default is 4 AM, after the 3 AM Lucene reindex in ScheduledSearchReindexer so the two heavy nightly passes don't race for the connection pool.

Multi-container concurrency is benign: HomeStatsService.refresh() writes to disk atomically (temp file + ATOMIC_MOVE) and the recompute itself is read-only, so two nodes racing the same tick at worst do the work twice.

  • Constructor Details

    • HomeStatsRefresher

      public HomeStatsRefresher()
  • Method Details

    • refreshOnStartup

      @EventListener(org.springframework.context.event.ContextRefreshedEvent.class) public void refreshOnStartup()
      Recompute the snapshot on context startup. Always runs (no skip-if-cached) so a fresh redeploy picks up new aggregation shape immediately — the on-disk snapshot loaded by HomeStatsServiceImpl.afterPropertiesSet() is what GET /stats/home serves until this background refresh completes; the stale-from-previous-build data stays available rather than 503-ing, but it's replaced as soon as the new compute finishes.

      Runs in a background thread so the cold-cache aggregation pass (~15-25s on a fresh DB cache) doesn't block Spring startup.

    • refreshDaily

      @Scheduled(cron="${gemma.homeStats.refresh.cron:0 0 4 * * *}") public void refreshDaily()
      Daily refresh. Default cron: 4 AM, after ScheduledSearchReindexer. Only fires on nodes with @EnableScheduling active (the production scheduler profile); local-dev containers rely on the startup pass above.