FindRelevantService
package com.blizzard.meetups.api.service.findrelevant;
import com.blizzard.meetups.api.core.enums.Community;
import com.blizzard.meetups.api.data.MeetupMetaData;
import com.blizzard.meetups.api.domain.Meetup;
import com.blizzard.meetups.api.domain.MeetupRepository;
import com.blizzard.meetups.api.metrics.FindRelevantMetricsService;
import com.blizzard.meetups.api.service.DistanceService;
import com.blizzard.meetups.api.service.endpointcache.EndpointCacheService;
import com.blizzard.meetups.api.util.Timer;
import com.blizzard.meetups.api.web.io.FindRelevantRequestParameters;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import static com.blizzard.meetups.api.service.endpointcache.EndpointCacheService.EndpointCacheMode.CACHE_MEETUPS;
import static com.blizzard.meetups.api.web.misc.SortComparator.byDistance;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.toList;
@Service
public class FindRelevantService {
private static final Logger LOGGER = LoggerFactory.getLogger(FindRelevantService.class);
private final CachedFindRelevantService cached;
private final UncachedFindRelevantService uncached;
private final DistanceService distanceService;
private final MeetupRepository meetupRepository;
private final FindRelevantMetricsService metricsService;
private final EndpointCacheService endpointCacheService;
public FindRelevantService(CachedFindRelevantService cached,
UncachedFindRelevantService uncached,
DistanceService distanceService,
MeetupRepository meetupRepository,
FindRelevantMetricsService metricsService,
EndpointCacheService endpointCacheService) {
this.cached = cached;
this.uncached = uncached;
this.distanceService = distanceService;
this.meetupRepository = meetupRepository;
this.metricsService = metricsService;
this.endpointCacheService = endpointCacheService;
}
/**
* <pre>
* withinTimeWindow = startTime < minutesAfter && endTime > minutesBefore
* Query logic:
* =======================================================================================================================================================================================================
* |-------------------------------------------------------------TWO------------------------------------------------------------------|
* |-----------------------------------------------ONE-----------------------------------------|
* |---------------ZERO------------------|
* withinTimeWindow AND isCommunityMatch AND matchesAllProperties AND (belongsToOrganizer OR isCheckedIn OR ((nearLocation OR matchesAnyIdentifiers) AND isApprovalStatusMatch AND matchesAllIdentifiers))
* ========================================================================================================================================================================================================
* </pre>
*/
public Page<MeetupMetaData> findRelevantMeetups(FindRelevantRequestParameters frrp, Pageable page) {
metricsService.addAttributesToNewRelicTransaction(singletonMap("findRelevant.service.endpointCacheMode", CACHE_MEETUPS));
Long before = frrp.getMinutesBefore();
Long after = frrp.getMinutesAfter();
Community community = frrp.getCommunity();
Timer frTimer = Timer.begin("01_findMeetups");
List<Meetup> unfiltered = cached.findRelevantMeetups(before, after, community);
frTimer.switchTo("03_filterCachedMeetupsToActuallyRelevant");
List<Meetup> filteredMeetups = unfiltered.stream()
.filter(matches(frrp))
.collect(toList());
List<MeetupMetaData> filteredMetaDatas = filteredMeetups.stream()
.map(toMeetupMetaData(frrp))
.sorted(byDistance)
.skip(page.getOffset())
.limit(page.getPageSize())
.collect(toList());
Page<MeetupMetaData> filteredMeetupMetaDatasPage = PageableExecutionUtils.getPage(filteredMetaDatas, page, filteredMeetups::size);
metricsService.addAttributesToNewRelicTransaction(Timer.asMap(frTimer.done(), "findRelevant.service"));
return filteredMeetupMetaDatasPage;
}
@SuppressWarnings("Duplicates")
public void clearEndpointCache() {
LOGGER.info("FindRelevantService.clearEndpointCache");
cached.clearEndpointCache();
}
@NotNull
private Predicate<Meetup> matches(FindRelevantRequestParameters frrp) {
return meetup -> cached.includedFor(frrp, meetup);
}
@NotNull
private Function<Meetup, MeetupMetaData> toMeetupMetaData(FindRelevantRequestParameters frrp) {
return distanceService.toMeetupMetaData(frrp.getLat(), frrp.getLng());
}
}