Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ java_library(
deps = [
":search_service_logic",
"//src/devtools/mobileharness/fe/v6/service/proto/search:search_fleet_java_proto",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/index:dimension_overlay",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/index:fleet_snapshot",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/index:overlay_view",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/query:device_corpus",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/query:fleet_chip_resolver",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/query:fleet_column_cataloger",
Expand All @@ -48,6 +50,7 @@ java_library(
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/query:host_corpus",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/query:scenario_curation",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/query:search_corpus",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/refresh:dimension_overlay_store",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/refresh:fleet_snapshot_store",
"@maven//:com_google_guava_guava",
"@maven//:javax_inject_jsr330_api",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

import static com.google.common.util.concurrent.Futures.immediateFuture;

import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.devtools.mobileharness.fe.v6.service.proto.search.Filter;
import com.google.devtools.mobileharness.fe.v6.service.proto.search.Fleet;
import com.google.devtools.mobileharness.fe.v6.service.proto.search.FleetChipResolverRequest;
import com.google.devtools.mobileharness.fe.v6.service.proto.search.FleetChipResolverResponse;
Expand All @@ -42,7 +44,9 @@
import com.google.devtools.mobileharness.fe.v6.service.proto.search.FleetValueListRequest;
import com.google.devtools.mobileharness.fe.v6.service.proto.search.FleetValueListResponse;
import com.google.devtools.mobileharness.fe.v6.service.proto.search.SearchEntity;
import com.google.devtools.mobileharness.fe.v6.service.search.index.DimensionOverlay;
import com.google.devtools.mobileharness.fe.v6.service.search.index.FleetSnapshot;
import com.google.devtools.mobileharness.fe.v6.service.search.index.OverlayView;
import com.google.devtools.mobileharness.fe.v6.service.search.query.DeviceCorpus;
import com.google.devtools.mobileharness.fe.v6.service.search.query.FleetChipResolver;
import com.google.devtools.mobileharness.fe.v6.service.search.query.FleetColumnCataloger;
Expand All @@ -55,8 +59,11 @@
import com.google.devtools.mobileharness.fe.v6.service.search.query.HostCorpus;
import com.google.devtools.mobileharness.fe.v6.service.search.query.ScenarioCuration;
import com.google.devtools.mobileharness.fe.v6.service.search.query.SearchCorpus;
import com.google.devtools.mobileharness.fe.v6.service.search.refresh.DimensionOverlayStore;
import com.google.devtools.mobileharness.fe.v6.service.search.refresh.FleetSnapshotStore;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;

Expand All @@ -82,6 +89,7 @@ public final class SearchServiceLogicImpl implements SearchServiceLogic {

private final ListeningExecutorService executor;
private final FleetSnapshotStore store;
private final DimensionOverlayStore overlayStore;
private final Map<Fleet, ScenarioCuration> curations;
private final FleetSearchConfigProvider searchConfigProvider;
private final FleetFlatSearcher flatSearcher;
Expand All @@ -96,6 +104,7 @@ public final class SearchServiceLogicImpl implements SearchServiceLogic {
SearchServiceLogicImpl(
ListeningExecutorService executor,
FleetSnapshotStore store,
DimensionOverlayStore overlayStore,
Map<Fleet, ScenarioCuration> curations,
FleetSearchConfigProvider searchConfigProvider,
FleetFlatSearcher flatSearcher,
Expand All @@ -107,6 +116,7 @@ public final class SearchServiceLogicImpl implements SearchServiceLogic {
FleetColumnCataloger columnCataloger) {
this.executor = executor;
this.store = store;
this.overlayStore = overlayStore;
this.curations = curations;
this.searchConfigProvider = searchConfigProvider;
this.flatSearcher = flatSearcher;
Expand Down Expand Up @@ -134,12 +144,18 @@ public ListenableFuture<FleetSearchConfig> getFleetSearchConfig(

@Override
public ListenableFuture<FleetSearchResults> searchFleet(FleetSearchRequest request) {
return Futures.submit(() -> searchFleetSync(request), executor);
Fleet fleet = normalize(request.getFleet());
Set<String> referencedKeys = extractReferencedKeys(request);
return Futures.transformAsync(
overlayStore.loadOverlaysAsync(fleet, referencedKeys, executor),
overlays -> Futures.submit(() -> searchFleetSync(request, overlays), executor),
executor);
}

private FleetSearchResults searchFleetSync(FleetSearchRequest request) {
private FleetSearchResults searchFleetSync(
FleetSearchRequest request, ImmutableMap<String, DimensionOverlay> overlays) {
Fleet fleet = normalize(request.getFleet());
SearchCorpus corpus = corpus(fleet, request.getEntity());
SearchCorpus corpus = corpus(fleet, request.getEntity(), overlays);
return switch (request.getViewCase()) {
case FLAT -> {
FleetFlatView flat = request.getFlat();
Expand Down Expand Up @@ -174,8 +190,6 @@ private FleetSearchResults searchFleetSync(FleetSearchRequest request) {
expand.getPageToken());
yield FleetSearchResults.newBuilder().setFlat(results).build();
}
// A request with no view selects no results shape, so return an empty result rather than
// guessing a view.
case VIEW_NOT_SET -> FleetSearchResults.getDefaultInstance();
};
}
Expand All @@ -196,9 +210,6 @@ public ListenableFuture<FleetChipResolverResponse> resolveFleetChips(
FleetChipResolverRequest request) {
return Futures.submit(
() -> {
// Chip resolution is stateless: the request carries no fleet, and the resolver reads only
// key display names and value casing, which are the same across fleets. Read the self
// snapshot.
FleetSnapshot snapshot = store.get(Fleet.FLEET_SELF);
return chipResolver.resolve(snapshot, request);
},
Expand All @@ -207,12 +218,18 @@ public ListenableFuture<FleetChipResolverResponse> resolveFleetChips(

@Override
public ListenableFuture<FleetValueListResponse> getFleetValueList(FleetValueListRequest request) {
return Futures.submit(
() -> {
Fleet fleet = normalize(request.getFleet());
return valueLister.listValues(
corpus(fleet, request.getEntity()), request.getKey(), request.getFiltersList());
},
Fleet fleet = normalize(request.getFleet());
Set<String> keys = extractReferencedKeys(request);
return Futures.transformAsync(
overlayStore.loadOverlaysAsync(fleet, keys, executor),
overlays ->
Futures.submit(
() ->
valueLister.listValues(
corpus(fleet, request.getEntity(), overlays),
request.getKey(),
request.getFiltersList()),
executor),
executor);
}

Expand All @@ -238,22 +255,80 @@ public ListenableFuture<FleetColumnCatalogResponse> getFleetColumnCatalog(
executor);
}

/**
* Builds the search corpus for a fleet and entity. A host search projects the fleet through a
* {@link HostCorpus} over the host index and host posting lists; every other entity projects it
* through a {@link DeviceCorpus}. A missing curation is passed through as null so the promoted
* keys provider keeps its curation-missing fallback.
*/
private SearchCorpus corpus(Fleet fleet, SearchEntity entity) {
private SearchCorpus corpus(
Fleet fleet, SearchEntity entity, ImmutableMap<String, DimensionOverlay> overlays) {
if (entity == SearchEntity.SEARCH_ENTITY_HOST) {
return new HostCorpus(store.get(fleet), store.hostPostings(fleet), curations.get(fleet));
}
return new DeviceCorpus(store.get(fleet), store.postings(fleet), curations.get(fleet));
FleetSnapshot snapshot = store.get(fleet);
OverlayView overlayView = OverlayView.bind(snapshot, overlays);
return new DeviceCorpus(snapshot, store.postings(fleet), curations.get(fleet), overlayView);
}

private SearchCorpus corpus(Fleet fleet, SearchEntity entity) {
return corpus(fleet, entity, ImmutableMap.of());
}

private static Set<String> extractReferencedKeys(FleetSearchRequest request) {
Set<String> keys = new HashSet<>();
for (Filter filter : request.getFiltersList()) {
if (isOverlayKey(filter.getKey())) {
keys.add(filter.getKey());
}
}
switch (request.getViewCase()) {
case FLAT -> {
FleetFlatView flat = request.getFlat();
for (String col : flat.getColumnsList()) {
if (isOverlayKey(col)) {
keys.add(col);
}
}
if (flat.hasSort() && isOverlayKey(flat.getSort().getKey())) {
keys.add(flat.getSort().getKey());
}
}
case GROUP_HEADER -> {
FleetGroupHeaderView header = request.getGroupHeader();
for (String gb : header.getGroupByList()) {
if (isOverlayKey(gb)) {
keys.add(gb);
}
}
if (header.hasSort() && isOverlayKey(header.getSort().getField().getGroupKey())) {
keys.add(header.getSort().getField().getGroupKey());
}
}
case GROUP_EXPAND -> {
FleetGroupExpandView expand = request.getGroupExpand();
for (String col : expand.getColumnsList()) {
if (isOverlayKey(col)) {
keys.add(col);
}
}
}
case VIEW_NOT_SET -> {}
}
return keys;
}

private static Set<String> extractReferencedKeys(FleetValueListRequest request) {
Set<String> keys = new HashSet<>();
if (isOverlayKey(request.getKey())) {
keys.add(request.getKey());
}
for (Filter filter : request.getFiltersList()) {
if (isOverlayKey(filter.getKey())) {
keys.add(filter.getKey());
}
}
return keys;
}

private static boolean isOverlayKey(String keyId) {
return keyId != null && keyId.startsWith("dim::");
}

/**
* Normalizes an unspecified fleet to the self fleet, matching the {@code Fleet} proto default.
*/
private static Fleet normalize(Fleet fleet) {
return fleet == Fleet.FLEET_UNSPECIFIED ? Fleet.FLEET_SELF : fleet;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,25 @@ java_library(
],
)

java_library(
name = "dimension_overlay",
srcs = ["DimensionOverlay.java"],
deps = [
":fleet_snapshot",
"//src/java/com/google/devtools/mobileharness/fe/v6/service/search/pull:dimension_overlay_raw",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
],
)

java_library(
name = "overlay_view",
srcs = ["OverlayView.java"],
deps = ["@maven//:com_google_guava_guava"],
deps = [
":dimension_overlay",
":fleet_snapshot",
"@maven//:com_google_guava_guava",
],
)

java_library(
Expand Down
Loading
Loading