item service: process pending lookups in order

I think the current system causes starvation for item checking
This commit is contained in:
Adam
2018-03-04 17:09:01 -05:00
parent 451f13a424
commit 4620de3ded
2 changed files with 97 additions and 64 deletions

View File

@@ -84,9 +84,7 @@ public class ItemService
private static final int MAX_PENDING = 512; private static final int MAX_PENDING = 512;
private final Sql2o sql2o; private final Sql2o sql2o;
private final ConcurrentLinkedQueue<Integer> pendingPriceLookups = new ConcurrentLinkedQueue<>(); private final ConcurrentLinkedQueue<PendingLookup> pendingLookups = new ConcurrentLinkedQueue<PendingLookup>();
private final ConcurrentLinkedQueue<String> pendingSearches = new ConcurrentLinkedQueue<>();
private final ConcurrentLinkedQueue<Integer> pendingItems = new ConcurrentLinkedQueue<>();
@Autowired @Autowired
public ItemService(@Qualifier("Runelite SQL2O") Sql2o sql2o) public ItemService(@Qualifier("Runelite SQL2O") Sql2o sql2o)
@@ -365,91 +363,70 @@ public class ItemService
public void queuePriceLookup(int itemId) public void queuePriceLookup(int itemId)
{ {
if (pendingPriceLookups.size() >= MAX_PENDING) if (pendingLookups.size() < MAX_PENDING)
{ {
return; pendingLookups.add(new PendingLookup(itemId, PendingLookup.Type.PRICE));
}
else
{
log.warn("Dropping pending price lookup for {}", itemId);
} }
pendingPriceLookups.add(itemId);
} }
public void queueSearch(String search) public void queueSearch(String search)
{ {
if (pendingSearches.size() >= MAX_PENDING) if (pendingLookups.size() < MAX_PENDING)
{ {
return; pendingLookups.add(new PendingLookup(search, PendingLookup.Type.SEARCH));
}
else
{
log.warn("Dropping pending search for {}", search);
} }
pendingSearches.add(search);
} }
public void queueItem(int itemId) public void queueItem(int itemId)
{ {
if (pendingItems.size() >= MAX_PENDING) if (pendingLookups.size() < MAX_PENDING)
{ {
return; pendingLookups.add(new PendingLookup(itemId, PendingLookup.Type.ITEM));
}
else
{
log.warn("Dropping pending item lookup for {}", itemId);
} }
pendingItems.add(itemId);
} }
@Scheduled(fixedDelay = 5000) @Scheduled(fixedDelay = 5000)
public void check() public void check()
{ {
if (checkPrices()) PendingLookup pendingLookup = pendingLookups.poll();
if (pendingLookup == null)
{ {
return; return;
} }
if (checkSearches())
switch (pendingLookup.getType())
{ {
return; case PRICE:
fetchPrice(pendingLookup.getItemId());
break;
case SEARCH:
try
{
RSSearch reSearch = fetchRSSearch(pendingLookup.getSearch());
batchInsertItems(reSearch);
}
catch (IOException ex)
{
log.warn("error while searching items", ex);
}
break;
case ITEM:
fetchItem(pendingLookup.getItemId());
break;
} }
checkItems();
} }
private boolean checkPrices()
{
Integer itemId = pendingPriceLookups.poll();
if (itemId == null)
{
return false;
}
fetchPrice(itemId);
return true;
}
private boolean checkSearches()
{
String search = pendingSearches.poll();
if (search == null)
{
return false;
}
try
{
RSSearch reSearch = fetchRSSearch(search);
batchInsertItems(reSearch);
}
catch (IOException ex)
{
log.warn("error while searching items", ex);
}
return true;
}
private boolean checkItems()
{
Integer itemId = pendingItems.poll();
if (itemId == null)
{
return false;
}
fetchItem(itemId);
return true;
}
} }

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service.item;
import lombok.Value;
@Value
class PendingLookup
{
enum Type
{
PRICE,
SEARCH,
ITEM;
}
private final int itemId;
private final String search;
private final Type type;
public PendingLookup(int itemId, Type type)
{
this.itemId = itemId;
this.search = null;
this.type = type;
}
public PendingLookup(String search, Type type)
{
this.itemId = -1;
this.search = search;
this.type = type;
}
}