item manager: add batch item price lookup

This commit is contained in:
Adam
2018-03-18 11:32:48 -04:00
parent c12dc9b6c7
commit adc5fe2b26

View File

@@ -29,6 +29,10 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -36,6 +40,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM;
import net.runelite.api.ItemComposition;
@@ -45,6 +50,7 @@ import net.runelite.http.api.item.ItemPrice;
import net.runelite.http.api.item.SearchResult;
@Singleton
@Slf4j
public class ItemManager
{
@Value
@@ -58,17 +64,19 @@ public class ItemManager
/**
* not yet looked up
*/
static final ItemPrice EMPTY = new ItemPrice();
/**
* has no price
*/
static final ItemPrice NONE = new ItemPrice();
private final Client client;
private final ScheduledExecutorService scheduledExecutorService;
private final ItemClient itemClient = new ItemClient();
private final LoadingCache<String, SearchResult> itemSearches;
private final LoadingCache<Integer, ItemPrice> itemPrices;
private final LoadingCache<Integer, ItemPrice> itemPriceCache;
private final LoadingCache<ImageKey, BufferedImage> itemImages;
private final LoadingCache<Integer, ItemComposition> itemCompositions;
@@ -76,8 +84,10 @@ public class ItemManager
public ItemManager(@Nullable Client client, ScheduledExecutorService executor)
{
this.client = client;
itemPrices = CacheBuilder.newBuilder()
.maximumSize(512L)
this.scheduledExecutorService = executor;
itemPriceCache = CacheBuilder.newBuilder()
.maximumSize(1024L)
.expireAfterAccess(1, TimeUnit.HOURS)
.build(new ItemPriceLoader(executor, itemClient));
@@ -126,16 +136,74 @@ public class ItemManager
*/
public ItemPrice getItemPriceAsync(int itemId)
{
ItemPrice itemPrice = itemPrices.getIfPresent(itemId);
ItemPrice itemPrice = itemPriceCache.getIfPresent(itemId);
if (itemPrice != null && itemPrice != EMPTY)
{
return itemPrice == NONE ? null : itemPrice;
}
itemPrices.refresh(itemId);
itemPriceCache.refresh(itemId);
return null;
}
/**
* Look up bulk item prices asynchronously
*
* @param itemIds array of item Ids
* @return a future called with the looked up prices
*/
public CompletableFuture<ItemPrice[]> getItemPriceBatch(List<Integer> itemIds)
{
final List<Integer> lookup = new ArrayList<>();
final List<ItemPrice> existing = new ArrayList<>();
for (int itemId : itemIds)
{
ItemPrice itemPrice = itemPriceCache.getIfPresent(itemId);
if (itemPrice != null)
{
existing.add(itemPrice);
}
else
{
lookup.add(itemId);
}
}
// All cached?
if (lookup.isEmpty())
{
return CompletableFuture.completedFuture(existing.toArray(new ItemPrice[existing.size()]));
}
final CompletableFuture<ItemPrice[]> future = new CompletableFuture<>();
scheduledExecutorService.execute(() ->
{
try
{
// Do a query for the items not in the cache
ItemPrice[] itemPrices = itemClient.lookupItemPrice(lookup.toArray(new Integer[lookup.size()]));
if (itemPrices != null)
{
for (int itemId : lookup)
{
itemPriceCache.put(itemId, NONE);
}
for (ItemPrice itemPrice : itemPrices)
{
itemPriceCache.put(itemPrice.getItem().getId(), itemPrice);
}
// Append these to the already cached items
Arrays.stream(itemPrices).forEach(existing::add);
}
future.complete(existing.toArray(new ItemPrice[existing.size()]));
}
catch (Exception ex)
{
future.completeExceptionally(ex);
}
});
return future;
}
/**
* Look up an item's price synchronously
*
@@ -145,7 +213,7 @@ public class ItemManager
*/
public ItemPrice getItemPrice(int itemId) throws IOException
{
ItemPrice itemPrice = itemPrices.getIfPresent(itemId);
ItemPrice itemPrice = itemPriceCache.getIfPresent(itemId);
if (itemPrice != null && itemPrice != EMPTY)
{
return itemPrice == NONE ? null : itemPrice;
@@ -154,11 +222,11 @@ public class ItemManager
itemPrice = itemClient.lookupItemPrice(itemId);
if (itemPrice == null)
{
itemPrices.put(itemId, NONE);
itemPriceCache.put(itemId, NONE);
return null;
}
itemPrices.put(itemId, itemPrice);
itemPriceCache.put(itemId, itemPrice);
return itemPrice;
}