Add method on Index to look up a single document by key

Now that we have Java 8, it is easy to provide a default
implementation using a default method. The only thing subinterfaces
need to provide is a way to construct a predicate matching exactly
one document by key. Index backend authors may also choose to provide
a more efficient implementation if necessary.

Change-Id: I7d9de2f9c947ced9411b69ed39606dc4ba0b599a
This commit is contained in:
Dave Borowitz
2016-09-21 14:33:09 +02:00
parent c04343eaad
commit 47fee2a156
5 changed files with 57 additions and 2 deletions

View File

@@ -17,8 +17,11 @@ package com.google.gerrit.server.index;
import com.google.gerrit.server.query.DataSource;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException;
import com.google.gwtorm.server.OrmException;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
/**
* Secondary index implementation for arbitrary documents.
@@ -90,6 +93,44 @@ public interface Index<K, V> {
DataSource<V> getSource(Predicate<V> p, QueryOptions opts)
throws QueryParseException;
/**
* Get a single document from the index.
*
* @param key document key.
* @param opts query options. Options that do not make sense in the context of
* a single document, such as start, will be ignored.
* @return a single document if present.
* @throws IOException
*/
default Optional<V> get(K key, QueryOptions opts) throws IOException {
opts = opts.withStart(0).withLimit(2);
List<V> results;
try {
results = getSource(keyPredicate(key), opts).read().toList();
} catch (QueryParseException e) {
throw new IOException("Unexpected QueryParseException during get()", e);
} catch (OrmException e) {
throw new IOException(e);
}
switch (results.size()) {
case 0:
return Optional.empty();
case 1:
return Optional.of(results.get(0));
default:
throw new IOException("Multiple results found in index for key "
+ key + ": " + results);
}
}
/**
* Get a predicate that looks up a single document by key.
*
* @param key document key.
* @return a single predicate.
*/
Predicate<V> keyPredicate(K key);
/**
* Mark whether this index is up-to-date and ready to serve reads.
*

View File

@@ -18,9 +18,16 @@ import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.account.AccountPredicates;
public interface AccountIndex extends Index<Account.Id, AccountState> {
public interface Factory extends
IndexDefinition.IndexFactory<Account.Id, AccountState, AccountIndex> {
}
@Override
default Predicate<AccountState> keyPredicate(Account.Id id) {
return AccountPredicates.id(id);
}
}

View File

@@ -17,10 +17,17 @@ package com.google.gerrit.server.index.change;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.LegacyChangeIdPredicate;
public interface ChangeIndex extends Index<Change.Id, ChangeData> {
public interface Factory extends
IndexDefinition.IndexFactory<Change.Id, ChangeData, ChangeIndex> {
}
@Override
default Predicate<ChangeData> keyPredicate(Change.Id id) {
return new LegacyChangeIdPredicate(id);
}
}