// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.remote;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.devtools.build.lib.remote.util.Utils.getFromFuture;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

import build.bazel.remote.execution.v2.Digest;
import build.bazel.remote.execution.v2.RequestMetadata;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.flogger.GoogleLogger;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionCacheUtils;
import com.google.devtools.build.lib.actions.ActionLookupData;
import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
import com.google.devtools.build.lib.actions.cache.ActionCache;
import com.google.devtools.build.lib.actions.cache.ActionCache.Entry;
import com.google.devtools.build.lib.actions.cache.ActionCache.Entry.SerializableTreeArtifactValue;
import com.google.devtools.build.lib.concurrent.ExecutorUtil;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.remote.LeaseService.LeaseExtension;
import com.google.devtools.build.lib.remote.common.RemoteActionExecutionContext;
import com.google.devtools.build.lib.remote.util.DigestUtil;
import com.google.devtools.build.lib.remote.util.TracingMetadataUtils;
import com.google.devtools.build.lib.skyframe.ActionExecutionValue;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
import com.google.devtools.build.skyframe.MemoizingEvaluator;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/** A {@link LeaseExtension} implementation that uses REAPI. */
public class RemoteLeaseExtension implements LeaseExtension {
  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
  private static final Predicate<SkyKey> ACTION_FILTER =
      SkyFunctionName.functionIs(SkyFunctions.ACTION_EXECUTION);

  private final ScheduledExecutorService scheduledExecutor =
      Executors.newSingleThreadScheduledExecutor(
          new ThreadFactoryBuilder().setNameFormat("lease-extension-%d").build());

  private final ReentrantLock lock = new ReentrantLock();

  private final MemoizingEvaluator memoizingEvaluator;
  @Nullable private final ActionCache actionCache;
  private final RemoteCache remoteCache;
  private final Duration remoteCacheTtl;
  private final RemoteActionExecutionContext context;

  public RemoteLeaseExtension(
      MemoizingEvaluator memoizingEvaluator,
      @Nullable ActionCache actionCache,
      String buildRequestId,
      String commandId,
      RemoteCache remoteCache,
      Duration remoteCacheTtl) {
    this.memoizingEvaluator = memoizingEvaluator;
    this.actionCache = actionCache;
    this.remoteCache = remoteCache;
    this.remoteCacheTtl = remoteCacheTtl;
    RequestMetadata requestMetadata =
        TracingMetadataUtils.buildMetadata(buildRequestId, commandId, "lease-extension", null);
    this.context = RemoteActionExecutionContext.create(requestMetadata);
  }

  @Override
  public void start() {
    // Immediately extend leases for outputs that are already known to skyframe. For clean build,
    // the set of outputs is empty. For incremental build, it contains outputs that were not
    // invalidated after skyframe's dirtiness check.
    var unused = scheduledExecutor.schedule(this::extendLeases, 0, MILLISECONDS);
  }

  private void extendLeases() {
    // Acquire the lock to prevent multiple doExtendLeases() running.
    lock.lock();
    try (var silentCloseable = Profiler.instance().profile("doExtendLeases")) {
      doExtendLeases();
    } finally {
      lock.unlock();
    }
  }

  private void doExtendLeases() {
    var valuesMap = memoizingEvaluator.getValues();
    // We will extend leases for all known outputs so the earliest time when one output could be
    // expired is (now + ttl).
    var earliestExpiration = Instant.now().plus(remoteCacheTtl);

    try {
      for (var entry : valuesMap.entrySet()) {
        SkyKey key = entry.getKey();
        SkyValue value = entry.getValue();
        if (value != null && ACTION_FILTER.test(key)) {
          var action = getActionFromSkyKey(key);
          var actionExecutionValue = (ActionExecutionValue) value;
          var remoteFiles = collectRemoteFiles(actionExecutionValue);
          if (!remoteFiles.isEmpty()) {
            // Lease extensions are performed on action basis, not by collecting all outputs and
            // issue one giant `FindMissingBlobs` call to avoid increasing memory footprint. Since
            // this happens in the background, increased network calls are acceptable.
            try (var silentCloseable1 = Profiler.instance().profile(action.describe())) {
              extendLeaseForAction(action, remoteFiles, earliestExpiration.toEpochMilli());
            }
          }
        }
      }
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      return;
    } catch (Throwable e) {
      logger.atWarning().withCause(e).log("Failed to extend the lease");
    }

    // Only extend the leases again when one of the outputs is about to expire.
    var now = Instant.now();
    Duration delay;
    if (earliestExpiration.isAfter(now)) {
      delay = Duration.between(now, earliestExpiration);
    } else {
      delay = Duration.ZERO;
    }
    var unused = scheduledExecutor.schedule(this::extendLeases, delay.toMillis(), MILLISECONDS);
  }

  private static boolean isRemoteMetadataWithTtl(FileArtifactValue metadata) {
    return metadata.isRemote() && ((RemoteFileArtifactValue) metadata).getExpireAtEpochMilli() >= 0;
  }

  private ImmutableList<Map.Entry<? extends Artifact, FileArtifactValue>> collectRemoteFiles(
      ActionExecutionValue actionExecutionValue) {
    var result = ImmutableList.<Map.Entry<? extends Artifact, FileArtifactValue>>builder();
    for (var entry : actionExecutionValue.getAllFileValues().entrySet()) {
      if (isRemoteMetadataWithTtl(entry.getValue())) {
        result.add(entry);
      }
    }

    for (var treeMetadata : actionExecutionValue.getAllTreeArtifactValues().values()) {
      for (var entry : treeMetadata.getChildValues().entrySet()) {
        if (isRemoteMetadataWithTtl(entry.getValue())) {
          result.add(entry);
        }
      }
    }

    return result.build();
  }

  /** Returns {@code true} iff the outputs of the action */
  private void extendLeaseForAction(
      Action action,
      ImmutableList<Map.Entry<? extends Artifact, FileArtifactValue>> remoteFiles,
      long expireAtEpochMilli)
      throws IOException, InterruptedException {
    ImmutableSet<Digest> missingDigests;
    try (var silentCloseable = Profiler.instance().profile("findMissingDigests")) {
      // We assume remote server will extend the leases for all referenced blobs by a
      // FindMissingBlobs call.
      missingDigests =
          getFromFuture(
              remoteCache.findMissingDigests(
                  context,
                  Iterables.transform(
                      remoteFiles, remoteFile -> buildDigest(remoteFile.getValue()))));
    }

    var token = getActionCacheToken(action);
    for (var remoteFile : remoteFiles) {
      var artifact = remoteFile.getKey();
      var metadata = (RemoteFileArtifactValue) remoteFile.getValue();
      // Only extend the lease for the remote output if it is still alive remotely.
      if (!missingDigests.contains(buildDigest(metadata))) {
        metadata.extendExpireAtEpochMilli(expireAtEpochMilli);
        if (token != null) {
          if (artifact instanceof TreeFileArtifact) {
            token.extendOutputTreeFile((TreeFileArtifact) artifact, expireAtEpochMilli);
          } else {
            token.extendOutputFile(artifact, expireAtEpochMilli);
          }
        }
      }
    }

    if (actionCache != null && token != null && token.dirty) {
      // Only update the action cache entry if the token was updated because it usually involves
      // serialization.
      actionCache.put(token.key, token.entry);
    }
  }

  @Override
  public void stop() {
    if (ExecutorUtil.uninterruptibleShutdownNow(scheduledExecutor)) {
      Thread.currentThread().interrupt();
    }
  }

  private static Digest buildDigest(FileArtifactValue metadata) {
    return DigestUtil.buildDigest(metadata.getDigest(), metadata.getSize());
  }

  private Action getActionFromSkyKey(SkyKey key) throws InterruptedException {
    var actionLookupData = (ActionLookupData) key.argument();
    var actionLookupValue =
        (ActionLookupValue)
            checkNotNull(
                memoizingEvaluator.getExistingValue(actionLookupData.getActionLookupKey()));
    return actionLookupValue.getAction(actionLookupData.getActionIndex());
  }

  @Nullable
  private ActionCacheToken getActionCacheToken(Action action) {
    if (actionCache != null) {
      var actionCacheEntryWithKey = ActionCacheUtils.getCacheEntryWithKey(actionCache, action);
      if (actionCacheEntryWithKey != null) {
        return new ActionCacheToken(
            actionCacheEntryWithKey.getKey(), actionCacheEntryWithKey.getValue());
      }
    }

    return null;
  }

  private static class ActionCacheToken {
    final String key;
    final ActionCache.Entry entry;
    private boolean dirty;

    ActionCacheToken(String key, Entry entry) {
      this.key = key;
      this.entry = entry;
    }

    void extendOutputFile(Artifact artifact, long expireAtEpochMilli) {
      var metadata = entry.getOutputFile(artifact);
      if (metadata != null) {
        metadata.extendExpireAtEpochMilli(expireAtEpochMilli);
        dirty = true;
      }
    }

    void extendOutputTreeFile(TreeFileArtifact treeFile, long expireAtEpochMilli) {
      SerializableTreeArtifactValue treeMetadata = entry.getOutputTree(treeFile.getParent());
      if (treeMetadata != null) {
        var metadata = treeMetadata.childValues().get(treeFile.getTreeRelativePathString());
        if (metadata != null) {
          metadata.extendExpireAtEpochMilli(expireAtEpochMilli);
          dirty = true;
        }
      }
    }
  }
}
