All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.index.change.ReindexChangesAfterRefUpdate Maven / Gradle / Ivy

There is a newer version: 3.11.0-rc3
Show newest version
// Copyright (C) 2014 The Android Open Source Project
//
// 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.gerrit.server.index.change;

import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static com.google.gerrit.server.query.change.ChangeData.asChanges;

import com.google.common.flogger.FluentLogger;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
import com.google.gerrit.server.change.MergeabilityComputationBehavior;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.QueueProvider.QueueType;
import com.google.gerrit.server.index.IndexExecutor;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.RequestContext;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.eclipse.jgit.lib.Config;

/**
 * Listener for ref update events that reindexes changes in case the updated Git reference was used
 * to compute contents of an index document.
 *
 * 

Reindexes any open changes that has a destination branch that was updated to ensure that * 'mergeable' is still current. */ public class ReindexChangesAfterRefUpdate implements GitBatchRefUpdateListener { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private final OneOffRequestContext requestContext; private final Provider queryProvider; private final ChangeIndexer.Factory changeIndexerFactory; private final ChangeIndexCollection changeIndexes; private final AllUsersName allUsersName; private final ListeningExecutorService executor; private final boolean enabled; @Inject ReindexChangesAfterRefUpdate( @GerritServerConfig Config cfg, OneOffRequestContext requestContext, Provider queryProvider, ChangeIndexer.Factory changeIndexerFactory, ChangeIndexCollection changeIndexes, AllUsersName allUsersName, @IndexExecutor(QueueType.BATCH) ListeningExecutorService executor) { this.requestContext = requestContext; this.queryProvider = queryProvider; this.changeIndexerFactory = changeIndexerFactory; this.changeIndexes = changeIndexes; this.allUsersName = allUsersName; this.executor = executor; this.enabled = MergeabilityComputationBehavior.fromConfig(cfg).includeInIndex(); } @Override public void onGitBatchRefUpdate(GitBatchRefUpdateListener.Event event) { if (allUsersName.get().equals(event.getProjectName())) { if (event.getUpdatedRefs().stream() .noneMatch(ru -> ru.getRefName().equals(RefNames.REFS_CONFIG))) { // The update is in All-Users and not on refs/meta/config. So it's not a change. Return // early. return; } } for (UpdatedRef ref : event.getUpdatedRefs()) { if (!enabled || ref.getRefName().startsWith(RefNames.REFS_CHANGES) || ref.getRefName().startsWith(RefNames.REFS_DRAFT_COMMENTS) || ref.getRefName().startsWith(RefNames.REFS_USERS)) { continue; } Futures.addCallback( executor.submit(new GetChanges(event.getProjectName(), ref)), new FutureCallback<>() { @Override public void onSuccess(List changes) { for (Change c : changes) { @SuppressWarnings("unused") Future possiblyIgnoredError = changeIndexerFactory .create(executor, changeIndexes) .indexAsync(c.getProject(), c.getId()); } } @Override public void onFailure(Throwable ignored) { // Logged by {@link GetChanges#call()}. } }, directExecutor()); } } private abstract class Task implements Callable { protected UpdatedRef updatedRef; protected Task(UpdatedRef updatedRef) { this.updatedRef = updatedRef; } @Override public final V call() throws Exception { try (ManualRequestContext ctx = requestContext.open()) { return impl(ctx); } catch (Exception e) { logger.atSevere().withCause(e).log("Failed to reindex changes after %s", updatedRef); throw e; } } protected abstract V impl(RequestContext ctx) throws Exception; @SuppressWarnings("unused") protected abstract void remove(); } private class GetChanges extends Task> { protected String projectName; private GetChanges(String projectName, UpdatedRef updatedRef) { super(updatedRef); this.projectName = projectName; } @Override protected List impl(RequestContext ctx) { String ref = updatedRef.getRefName(); Project.NameKey project = Project.nameKey(projectName); if (ref.equals(RefNames.REFS_CONFIG)) { return asChanges(queryProvider.get().byProjectOpen(project)); } return asChanges(queryProvider.get().byBranchNew(BranchNameKey.create(project, ref))); } @Override public String toString() { return "Get changes to reindex caused by " + updatedRef.getRefName() + " update of project " + projectName; } @Override protected void remove() {} } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy