diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java index 4a684f92dc..3e3a7fadcc 100644 --- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java +++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java @@ -336,6 +336,19 @@ public class LuceneChangeIndex implements ChangeIndex { } } + @SuppressWarnings("unchecked") + @Override + public void delete(int id) throws IOException { + Term idTerm = QueryBuilder.idTerm(id); + try { + Futures.allAsList( + openIndex.delete(idTerm), + closedIndex.delete(idTerm)).get(); + } catch (ExecutionException | InterruptedException e) { + throw new IOException(e); + } + } + @Override public void deleteAll() throws IOException { openIndex.deleteAll(); diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/QueryBuilder.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/QueryBuilder.java index dfe3f2d215..2365929531 100644 --- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/QueryBuilder.java +++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/QueryBuilder.java @@ -56,6 +56,10 @@ public class QueryBuilder { return intTerm(ID_FIELD, cd.getId().get()); } + public static Term idTerm(int id) { + return intTerm(ID_FIELD, id); + } + private final Schema schema; private final org.apache.lucene.util.QueryBuilder queryBuilder; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java index b9b92cb340..d3e97ca8ef 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java @@ -15,6 +15,7 @@ package com.google.gerrit.server.change; import com.google.common.collect.ImmutableList; +import com.google.common.primitives.Ints; import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.restapi.AcceptsPost; import com.google.gerrit.extensions.restapi.IdString; @@ -26,6 +27,7 @@ import com.google.gerrit.extensions.restapi.TopLevelResource; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.index.ChangeIndexer; import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.NoSuchChangeException; import com.google.gerrit.server.query.change.QueryChanges; @@ -34,6 +36,7 @@ import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; +import java.io.IOException; import java.util.Collections; import java.util.List; @@ -47,6 +50,7 @@ public class ChangesCollection implements private final Provider queryFactory; private final DynamicMap> views; private final CreateChange createChange; + private final ChangeIndexer changeIndexer; @Inject ChangesCollection( @@ -55,13 +59,15 @@ public class ChangesCollection implements ChangeControl.GenericFactory changeControlFactory, Provider queryFactory, DynamicMap> views, - CreateChange createChange) { + CreateChange createChange, + ChangeIndexer changeIndexer) { this.db = dbProvider; this.user = user; this.changeControlFactory = changeControlFactory; this.queryFactory = queryFactory; this.views = views; this.createChange = createChange; + this.changeIndexer = changeIndexer; } @Override @@ -78,6 +84,16 @@ public class ChangesCollection implements public ChangeResource parse(TopLevelResource root, IdString id) throws ResourceNotFoundException, OrmException { List changes = findChanges(id.encoded()); + if (changes.isEmpty()) { + Integer changeId = Ints.tryParse(id.get()); + if (changeId != null) { + try { + changeIndexer.delete(changeId); + } catch (IOException e) { + throw new ResourceNotFoundException(id.get(), e); + } + } + } if (changes.size() != 1) { throw new ResourceNotFoundException(id); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndex.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndex.java index a710a108a3..167367898a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndex.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndex.java @@ -72,6 +72,15 @@ public interface ChangeIndex { */ public void delete(ChangeData cd) throws IOException; + /** + * Delete a change document from the index by id. + * + * @param id change document id + * + * @throws IOException + */ + public void delete(int id) throws IOException; + /** * Delete all change documents from the index. * diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexer.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexer.java index 437f55927d..72cb88c90a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexer.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexer.java @@ -165,6 +165,17 @@ public class ChangeIndexer { } } + /** + * Synchronously delete a change by id. + * + * @param id change to delete. + */ + public void delete(int id) throws IOException { + for (ChangeIndex i : getWriteIndexes()) { + i.delete(id); + } + } + /** * Synchronously delete a change. * diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/DummyIndex.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/DummyIndex.java index 9f1c353876..ff554ff0ef 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/DummyIndex.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/DummyIndex.java @@ -57,4 +57,8 @@ public class DummyIndex implements ChangeIndex { @Override public void markReady(boolean ready) throws IOException { } + + @Override + public void delete(int id) throws IOException { + } } diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/index/FakeIndex.java b/gerrit-server/src/test/java/com/google/gerrit/server/index/FakeIndex.java index 1b6ae4eb1d..fc0fb32114 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/index/FakeIndex.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/index/FakeIndex.java @@ -22,6 +22,8 @@ import com.google.gerrit.server.query.change.ChangeDataSource; import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.ResultSet; +import java.io.IOException; + class FakeIndex implements ChangeIndex { static Schema V1 = new Schema<>(1, false, ImmutableList.> of( @@ -106,4 +108,8 @@ class FakeIndex implements ChangeIndex { public void markReady(boolean ready) { throw new UnsupportedOperationException(); } + + @Override + public void delete(int id) throws IOException { + } } diff --git a/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java b/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java index 8c8b0071ac..830db27106 100644 --- a/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java +++ b/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java @@ -189,13 +189,27 @@ class SolrChangeIndex implements ChangeIndex, LifecycleListener { String id = cd.getId().toString(); try { if (cd.change().getStatus().isOpen()) { - openIndex.deleteById(id); - commit(openIndex); + delete(id, openIndex); } else { - closedIndex.deleteById(id); - commit(closedIndex); + delete(id, closedIndex); } - } catch (OrmException | SolrServerException e) { + } catch (OrmException e) { + throw new IOException(e); + } + } + + @Override + public void delete(int id) throws IOException { + String idString = Integer.toString(id); + delete(idString, openIndex); + delete(idString, closedIndex); + } + + private void delete(String id, CloudSolrServer index) throws IOException { + try { + index.deleteById(id); + commit(index); + } catch (SolrServerException e) { throw new IOException(e); } }