Skip to content

Commit

Permalink
item manager: add batch item price lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam- committed Mar 18, 2018
1 parent b3207e1 commit ac6eef0
Showing 1 changed file with 77 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@
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;
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;
Expand All @@ -45,6 +50,7 @@
import net.runelite.http.api.item.SearchResult;

@Singleton
@Slf4j
public class ItemManager
{
@Value
Expand All @@ -58,26 +64,30 @@ private static class ImageKey
/**
* 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;

@Inject
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));

Expand Down Expand Up @@ -126,16 +136,74 @@ public ItemComposition load(Integer key) throws Exception
*/
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
*
Expand All @@ -145,7 +213,7 @@ public ItemPrice getItemPriceAsync(int itemId)
*/
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;
Expand All @@ -154,11 +222,11 @@ public ItemPrice getItemPrice(int itemId) throws IOException
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;
}

Expand Down

0 comments on commit ac6eef0

Please sign in to comment.