StatsService { @Transactional public GetFeatureStatisticsResponse getFeatureStatistics(GetFeatureStatisticsRequest request) throws IOException { validateRequest(request); StatisticsRetriever statisticsRetriever = getStatisticsRetriever(request.getStore()); FeatureSet featureSet = getFeatureSet(request.getFeatureSetId()); if (featureSet == null) { throw new IllegalArgumentException( String.format( "Illegal request. Unable to find feature set %s", request.getFeatureSetId())); } List<String> features = request.getFeaturesList(); if (features.size() == 0) { features = featureSet.getFeatures().stream() .filter(feature -> !feature.isArchived()) .map(Feature::getName) .collect(Collectors.toList()); } List<List<FeatureNameStatistics>> featureNameStatisticsList = new ArrayList<>(); if (request.getIngestionIdsCount() == 0) { Timestamp endDate = request.getEndDate(); Timestamp startDate = request.getStartDate(); long timestamp = startDate.getSeconds(); while (timestamp < endDate.getSeconds()) { List<FeatureNameStatistics> featureNameStatistics = getFeatureNameStatisticsByDate( statisticsRetriever, featureSet, features, timestamp, request.getForceRefresh()); if (featureNameStatistics.size() != 0) { featureNameStatisticsList.add(featureNameStatistics); } timestamp += 86400; } if (featureNameStatisticsList.size() == 0) { DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd"); DateTime startDateTime = new DateTime(startDate.getSeconds() * 1000, DateTimeZone.UTC); DateTime endDateTime = new DateTime(endDate.getSeconds() * 1000, DateTimeZone.UTC); throw new RetrievalException( String.format( "Unable to find any data over provided dates [%s, %s)", fmt.print(startDateTime), fmt.print(endDateTime))); } } else { for (String datasetId : request.getIngestionIdsList()) { List<FeatureNameStatistics> featureNameStatistics = getFeatureNameStatisticsByDataset( statisticsRetriever, featureSet, features, datasetId, request.getForceRefresh()); if (featureNameStatistics.size() != 0) { featureNameStatisticsList.add(featureNameStatistics); } } if (featureNameStatisticsList.size() == 0) { throw new RetrievalException( String.format( "Unable to find any data over provided data sets %s", request.getIngestionIdsList())); } } List<FeatureNameStatistics> featureNameStatistics = mergeStatistics(featureNameStatisticsList); long totalCount = getTotalCount(featureNameStatistics.get(0)); return GetFeatureStatisticsResponse.newBuilder() .setDatasetFeatureStatisticsList( DatasetFeatureStatisticsList.newBuilder() .addDatasets( DatasetFeatureStatistics.newBuilder() .setNumExamples(totalCount) .addAllFeatures(featureNameStatistics))) .build(); } @Autowired  StatsService(
      StoreRepository storeRepository,
      FeatureStatisticsRepository featureStatisticsRepository,
      FeatureSetRepository featureSetRepository); @Transactional GetFeatureStatisticsResponse getFeatureStatistics(GetFeatureStatisticsRequest request); @VisibleForTesting List<FeatureNameStatistics> mergeStatistics(
      List<List<FeatureNameStatistics>> featureNameStatistics);  }
@Test public void shouldThrowExceptionIfNeitherDatesNorDatasetsProvided() throws IOException { GetFeatureStatisticsRequest request = GetFeatureStatisticsRequest.newBuilder().build(); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage( "Invalid request. Either provide dataset ids to retrieve statistics over, or a start date and end date."); statsService.getFeatureStatistics(request); }
@Test public void shouldThrowExceptionIfInvalidDatesProvided() throws IOException { GetFeatureStatisticsRequest request = GetFeatureStatisticsRequest.newBuilder() .setStartDate(Timestamp.newBuilder().setSeconds(1)) .setEndDate(Timestamp.newBuilder().setSeconds(0)) .build(); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage( "Invalid request. Start timestamp 1 is greater than the end timestamp 0"); statsService.getFeatureStatistics(request); }
@Test public void shouldThrowExceptionIfInvalidStoreProvided() throws IOException { GetFeatureStatisticsRequest request = GetFeatureStatisticsRequest.newBuilder() .setStartDate(Timestamp.newBuilder().setSeconds(0)) .setEndDate(Timestamp.newBuilder().setSeconds(1)) .setStore("redis") .build(); when(storeRepository.findById("redis")) .thenReturn( Optional.of( Store.fromProto( StoreProto.Store.newBuilder() .setName("redis") .setType(StoreType.REDIS) .build()))); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage( "Invalid store redis with type REDIS specified. Batch statistics are only supported for BigQuery stores"); statsService.getFeatureStatistics(request); }