http-service: fix item price cache to use fetched time instead of price time

Reduce cache duration to 30 minutes
This commit is contained in:
Adam
2018-01-10 11:44:56 -05:00
parent a87a969c70
commit ad8b2e82d1
2 changed files with 29 additions and 20 deletions

View File

@@ -30,6 +30,7 @@ import com.google.gson.JsonParseException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
@@ -69,6 +70,8 @@ public class ItemService
private static final HttpUrl RS_PRICE_URL = HttpUrl.parse(BASE + "/api/graph"); private static final HttpUrl RS_PRICE_URL = HttpUrl.parse(BASE + "/api/graph");
private static final HttpUrl RS_SEARCH_URL = HttpUrl.parse(BASE + "/api/catalogue/items.json?category=1"); private static final HttpUrl RS_SEARCH_URL = HttpUrl.parse(BASE + "/api/catalogue/items.json?category=1");
private static final Duration CACHE_DUATION = Duration.ofMinutes(30);
private static final String CREATE_ITEMS = "CREATE TABLE IF NOT EXISTS `items` (\n" private static final String CREATE_ITEMS = "CREATE TABLE IF NOT EXISTS `items` (\n"
+ " `id` int(11) NOT NULL,\n" + " `id` int(11) NOT NULL,\n"
+ " `name` tinytext NOT NULL,\n" + " `name` tinytext NOT NULL,\n"
@@ -83,16 +86,15 @@ public class ItemService
private static final String CREATE_PRICES = "CREATE TABLE IF NOT EXISTS `prices` (\n" private static final String CREATE_PRICES = "CREATE TABLE IF NOT EXISTS `prices` (\n"
+ " `item` int(11) NOT NULL,\n" + " `item` int(11) NOT NULL,\n"
+ " `price` int(11) NOT NULL,\n" + " `price` int(11) NOT NULL,\n"
+ " `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n" + " `time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
+ " KEY `item` (`item`)\n" + " `fetched_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
+ " UNIQUE KEY `item_time` (`item`,`time`),\n"
+ " KEY `item_fetched_time` (`item`,`fetched_time`)\n"
+ ") ENGINE=InnoDB"; + ") ENGINE=InnoDB";
private static final String CREATE_PRICES_FK = "ALTER TABLE `prices`\n" private static final String CREATE_PRICES_FK = "ALTER TABLE `prices`\n"
+ " ADD CONSTRAINT `item` FOREIGN KEY (`item`) REFERENCES `items` (`id`);"; + " ADD CONSTRAINT `item` FOREIGN KEY (`item`) REFERENCES `items` (`id`);";
private static final String CREATE_PRICES_IDX = "ALTER TABLE `prices`\n"
+ " ADD UNIQUE KEY `item` (`item`,`time`);";
private static final String RUNELITE_CACHE = "RuneLite-Cache"; private static final String RUNELITE_CACHE = "RuneLite-Cache";
private final Sql2o sql2o; private final Sql2o sql2o;
@@ -122,16 +124,6 @@ public class ItemService
{ {
// Ignore, happens when index already exists // Ignore, happens when index already exists
} }
try
{
con.createQuery(CREATE_PRICES_IDX)
.executeUpdate();
}
catch (Sql2oException ex)
{
// Ignore
}
} }
} }
@@ -234,9 +226,10 @@ public class ItemService
} }
else else
{ {
Instant yesterday = now.minus(1, ChronoUnit.DAYS); Instant cacheTime = now.minus(CACHE_DUATION);
if (priceEntry == null || priceEntry.getTime().isBefore(yesterday)) if (priceEntry == null || priceEntry.getFetched_time().isBefore(cacheTime))
{ {
// Price is unknown, or was fetched too long ago
List<PriceEntry> prices = fetchPrice(itemId); List<PriceEntry> prices = fetchPrice(itemId);
if (prices == null || prices.isEmpty()) if (prices == null || prices.isEmpty())
@@ -244,6 +237,7 @@ public class ItemService
return null; return null;
} }
// Get the most recent price
priceEntry = prices.get(prices.size() - 1); priceEntry = prices.get(prices.size() - 1);
hit = false; hit = false;
} }
@@ -330,14 +324,14 @@ public class ItemService
{ {
if (time != null) if (time != null)
{ {
return con.createQuery("select price, time from prices where item = :item and time <= :time order by time desc limit 1") 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("item", itemId)
.addParameter("time", time.toString()) .addParameter("time", time.toString())
.executeAndFetchFirst(PriceEntry.class); .executeAndFetchFirst(PriceEntry.class);
} }
else else
{ {
return con.createQuery("select price, time from prices where item = :item order by time desc limit 1") return con.createQuery("select item, price, time, fetched_time from prices where item = :item order by time desc limit 1")
.addParameter("item", itemId) .addParameter("item", itemId)
.executeAndFetchFirst(PriceEntry.class); .executeAndFetchFirst(PriceEntry.class);
} }
@@ -405,8 +399,10 @@ public class ItemService
{ {
RSPrices rsprice = fetchRSPrices(itemId); RSPrices rsprice = fetchRSPrices(itemId);
List<PriceEntry> entries = new ArrayList<>(); List<PriceEntry> entries = new ArrayList<>();
Instant now = Instant.now();
Query query = con.createQuery("insert ignore into prices (item, price, time) values (:item, :price, :time)"); Query query = con.createQuery("insert into prices (item, price, time, fetched_time) values (:item, :price, :time, :fetched_time) "
+ "ON DUPLICATE KEY UPDATE price = VALUES(price), fetched_time = VALUES(fetched_time)");
for (Entry<Long, Integer> entry : rsprice.getDaily().entrySet()) for (Entry<Long, Integer> entry : rsprice.getDaily().entrySet())
{ {
@@ -419,12 +415,14 @@ public class ItemService
priceEntry.setItem(itemId); priceEntry.setItem(itemId);
priceEntry.setPrice(price); priceEntry.setPrice(price);
priceEntry.setTime(time); priceEntry.setTime(time);
priceEntry.setFetched_time(now);
entries.add(priceEntry); entries.add(priceEntry);
query query
.addParameter("item", itemId) .addParameter("item", itemId)
.addParameter("price", price) .addParameter("price", price)
.addParameter("time", time) .addParameter("time", time)
.addParameter("fetched_time", now)
.addToBatch(); .addToBatch();
} }

View File

@@ -31,6 +31,7 @@ public class PriceEntry
private int item; private int item;
private int price; private int price;
private Instant time; private Instant time;
private Instant fetched_time;
public int getItem() public int getItem()
{ {
@@ -61,4 +62,14 @@ public class PriceEntry
{ {
this.time = time; this.time = time;
} }
public Instant getFetched_time()
{
return fetched_time;
}
public void setFetched_time(Instant fetched_time)
{
this.fetched_time = fetched_time;
}
} }