http-service: optimize bulk item price lookup

This commit is contained in:
Adam
2018-05-13 08:39:20 -04:00
parent ede2041a61
commit 274c79a7ba
2 changed files with 60 additions and 38 deletions

View File

@@ -28,11 +28,8 @@ import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -199,31 +196,20 @@ public class ItemController
itemIds = Arrays.copyOf(itemIds, MAX_BATCH_LOOKUP); itemIds = Arrays.copyOf(itemIds, MAX_BATCH_LOOKUP);
} }
Set<Integer> seen = new HashSet<>(); List<PriceEntry> prices = itemService.getPrices(itemIds);
List<ItemPrice> itemPrices = new ArrayList<>(itemIds.length);
for (int itemId : itemIds) return prices.stream()
{ .map(priceEntry ->
if (seen.contains(itemId))
{ {
continue; Item item = new Item();
} item.setId(priceEntry.getItem()); // fake item
seen.add(itemId);
ItemEntry item = itemService.getItem(itemId); ItemPrice itemPrice = new ItemPrice();
PriceEntry priceEntry = itemService.getPrice(itemId, null); itemPrice.setItem(item);
itemPrice.setPrice(priceEntry.getPrice());
if (item == null || priceEntry == null) itemPrice.setTime(priceEntry.getTime());
{ return itemPrice;
continue; })
} .toArray(ItemPrice[]::new);
ItemPrice itemPrice = new ItemPrice();
itemPrice.setItem(item.toItem());
itemPrice.setPrice(priceEntry.getPrice());
itemPrice.setTime(priceEntry.getTime());
itemPrices.add(itemPrice);
}
return itemPrices.toArray(new ItemPrice[itemPrices.size()]);
} }
} }

View File

@@ -30,8 +30,10 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.RuneLiteAPI;
@@ -123,23 +125,57 @@ public class ItemService
} }
} }
private PriceEntry getPrice(Connection con, int itemId, Instant time)
{
if (time != null)
{
return con.createQuery("select item, price, time, fetched_time from prices where item = :item and time <= :time order by time desc limit 1")
.addParameter("item", itemId)
.addParameter("time", time.toString())
.executeAndFetchFirst(PriceEntry.class);
}
else
{
return con.createQuery("select item, price, time, fetched_time from prices where item = :item order by time desc limit 1")
.addParameter("item", itemId)
.executeAndFetchFirst(PriceEntry.class);
}
}
public PriceEntry getPrice(int itemId, Instant time) public PriceEntry getPrice(int itemId, Instant time)
{ {
try (Connection con = sql2o.open()) try (Connection con = sql2o.open())
{ {
if (time != null) return getPrice(con, itemId, time);
}
}
public List<PriceEntry> getPrices(int... itemIds)
{
try (Connection con = sql2o.open())
{
Set<Integer> seen = new HashSet<>();
List<PriceEntry> priceEntries = new ArrayList<>(itemIds.length);
for (int itemId : itemIds)
{ {
return con.createQuery("select item, price, time, fetched_time from prices where item = :item and time <= :time order by time desc limit 1") if (seen.contains(itemId))
.addParameter("item", itemId) {
.addParameter("time", time.toString()) continue;
.executeAndFetchFirst(PriceEntry.class); }
} seen.add(itemId);
else
{ PriceEntry priceEntry = getPrice(con, itemId, null);
return con.createQuery("select item, price, time, fetched_time from prices where item = :item order by time desc limit 1")
.addParameter("item", itemId) if (priceEntry == null)
.executeAndFetchFirst(PriceEntry.class); {
continue;
}
priceEntries.add(priceEntry);
} }
return priceEntries;
} }
} }