private CompiledViewDefinitionWithGraphsImpl getCompiledViewDefinition(
      Instant valuationTime, VersionCorrection versionCorrection) {
    long functionInitId =
        getProcessContext()
            .getFunctionCompilationService()
            .getFunctionCompilationContext()
            .getFunctionInitId();
    CompiledViewDefinitionWithGraphsImpl compiledViewDefinition;
    updateViewDefinitionIfRequired();
    if (_compilationDirty) {
      _compilationDirty = false;
      invalidateCachedCompiledViewDefinition();
      compiledViewDefinition = null;
    } else {
      compiledViewDefinition = getCachedCompiledViewDefinition();
    }
    if (compiledViewDefinition != null
        && compiledViewDefinition.isValidFor(valuationTime)
        && functionInitId == compiledViewDefinition.getFunctionInitId()) {
      // Existing cached model is valid (an optimisation for the common case of similar, increasing
      // valuation times)
      return compiledViewDefinition;
    }

    try {
      MarketDataAvailabilityProvider availabilityProvider =
          getMarketDataProvider().getAvailabilityProvider();
      ViewCompilationServices compilationServices =
          getProcessContext().asCompilationServices(availabilityProvider);
      compiledViewDefinition =
          ViewDefinitionCompiler.compile(
              _viewDefinition, compilationServices, valuationTime, versionCorrection);

      if (isTerminated()) {
        return compiledViewDefinition; // [PLAT-1904] If we can't terminate the compilation at least
                                       // avoid doing the subscribe etc.
      }
    } catch (Exception e) {
      String message =
          MessageFormat.format(
              "Error compiling view definition {0} for time {1}",
              getViewProcess().getDefinitionId(), valuationTime);
      viewDefinitionCompilationFailed(valuationTime, new OpenGammaRuntimeException(message, e));
      throw new OpenGammaRuntimeException(message, e);
    }
    setCachedCompiledViewDefinition(compiledViewDefinition);
    // [PLAT-984]
    // Assume that valuation times are increasing in real-time towards the expiry of the view
    // definition, so that we
    // can predict the time to expiry. If this assumption is wrong then the worst we do is trigger
    // an unnecessary
    // cycle. In the predicted case, we trigger a cycle on expiry so that any new market data
    // subscriptions are made
    // straight away.
    if (compiledViewDefinition.getValidTo() != null) {
      Duration durationToExpiry =
          getMarketDataProvider()
              .getRealTimeDuration(valuationTime, compiledViewDefinition.getValidTo());
      long expiryNanos = System.nanoTime() + durationToExpiry.toNanosLong();
      _compilationExpiryCycleTrigger.set(expiryNanos, ViewCycleTriggerResult.forceFull());
    } else {
      _compilationExpiryCycleTrigger.reset();
    }

    // Notify the view that a (re)compilation has taken place before going on to do any
    // time-consuming work.
    // This might contain enough for clients to e.g. render an empty grid in which results will
    // later appear.
    viewDefinitionCompiled(compiledViewDefinition);

    // Update the market data subscriptions to whatever is now required, ensuring the computation
    // cycle can find the
    // required input data when it is executed.
    setMarketDataSubscriptions(compiledViewDefinition.getMarketDataRequirements().keySet());
    return compiledViewDefinition;
  }