fix issues with is_generous

-stop requesting blobs if price limit is reached and the offer still
has not been accepted

-drop max rate to old flat rate (0.005lbc/mb)
This commit is contained in:
Jack 2016-10-20 12:29:55 -04:00
parent a9ae1a1016
commit ea21821558
3 changed files with 35 additions and 10 deletions

View file

@ -1,5 +1,7 @@
from lbrynet.core.Strategy import get_default_strategy from lbrynet.core.Strategy import get_default_strategy
from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, MIN_BLOB_INFO_PAYMENT_RATE from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, MIN_BLOB_INFO_PAYMENT_RATE, is_generous_host
from decimal import Decimal
class BasePaymentRateManager(object): class BasePaymentRateManager(object):
def __init__(self, rate=MIN_BLOB_DATA_PAYMENT_RATE, info_rate=MIN_BLOB_INFO_PAYMENT_RATE): def __init__(self, rate=MIN_BLOB_DATA_PAYMENT_RATE, info_rate=MIN_BLOB_INFO_PAYMENT_RATE):
@ -34,7 +36,7 @@ class PaymentRateManager(object):
class NegotiatedPaymentRateManager(object): class NegotiatedPaymentRateManager(object):
def __init__(self, base, availability_tracker, generous=True): def __init__(self, base, availability_tracker, generous=is_generous_host):
""" """
@param base: a BasePaymentRateManager @param base: a BasePaymentRateManager
@param availability_tracker: a BlobAvailabilityTracker @param availability_tracker: a BlobAvailabilityTracker
@ -70,4 +72,10 @@ class NegotiatedPaymentRateManager(object):
self.points_paid += amount self.points_paid += amount
def record_offer_reply(self, peer, offer): def record_offer_reply(self, peer, offer):
self.strategy.update_accepted_offers(peer, offer) self.strategy.update_accepted_offers(peer, offer)
def price_limit_reached(self, peer):
if peer in self.strategy.pending_sent_offers:
offer = self.strategy.pending_sent_offers[peer]
return offer.is_too_low and round(Decimal.from_float(offer.rate), 5) >= round(self.strategy.max_rate, 5)
return False

View file

@ -1,5 +1,6 @@
from zope.interface import implementer from zope.interface import implementer
from decimal import Decimal from decimal import Decimal
from lbrynet.conf import is_generous_host
from lbrynet.interfaces import INegotiationStrategy from lbrynet.interfaces import INegotiationStrategy
from lbrynet.core.Offer import Offer from lbrynet.core.Offer import Offer
from lbrynet.core.PriceModel import MeanAvailabilityWeightedPrice from lbrynet.core.PriceModel import MeanAvailabilityWeightedPrice
@ -15,14 +16,14 @@ class Strategy(object):
""" """
implementer(INegotiationStrategy) implementer(INegotiationStrategy)
def __init__(self, price_model, max_rate, min_rate, is_generous=True): def __init__(self, price_model, max_rate, min_rate, is_generous=is_generous_host):
self.price_model = price_model self.price_model = price_model
self.is_generous = is_generous self.is_generous = is_generous
self.accepted_offers = {} self.accepted_offers = {}
self.pending_sent_offers = {} self.pending_sent_offers = {}
self.offers_sent = {} self.offers_sent = {}
self.offers_received = {} self.offers_received = {}
self.max_rate = max_rate or Decimal(self.price_model.base_price * 100) self.max_rate = max_rate or Decimal(self.price_model.base_price * 50)
self.min_rate = Decimal(min_rate) self.min_rate = Decimal(min_rate)
def _make_rate_offer(self, rates, offer_count): def _make_rate_offer(self, rates, offer_count):
@ -75,6 +76,7 @@ class Strategy(object):
del self.accepted_offers[peer] del self.accepted_offers[peer]
if offer.is_accepted: if offer.is_accepted:
self.accepted_offers.update({peer: offer}) self.accepted_offers.update({peer: offer})
self.pending_sent_offers.update({peer: offer})
def _add_offer_sent(self, peer): def _add_offer_sent(self, peer):
turn = self.offers_sent.get(peer, 0) + 1 turn = self.offers_sent.get(peer, 0) + 1
@ -99,7 +101,7 @@ class BasicAvailabilityWeightedStrategy(Strategy):
implementer(INegotiationStrategy) implementer(INegotiationStrategy)
def __init__(self, blob_tracker, acceleration=1.25, deceleration=0.9, max_rate=None, min_rate=0.0, def __init__(self, blob_tracker, acceleration=1.25, deceleration=0.9, max_rate=None, min_rate=0.0,
is_generous=True, base_price=0.0001, alpha=1.0): is_generous=is_generous_host, base_price=0.0001, alpha=1.0):
price_model = MeanAvailabilityWeightedPrice(blob_tracker, base_price=base_price, alpha=alpha) price_model = MeanAvailabilityWeightedPrice(blob_tracker, base_price=base_price, alpha=alpha)
Strategy.__init__(self, price_model, max_rate, min_rate, is_generous) Strategy.__init__(self, price_model, max_rate, min_rate, is_generous)
self._acceleration = Decimal(acceleration) # rate of how quickly to ramp offer self._acceleration = Decimal(acceleration) # rate of how quickly to ramp offer

View file

@ -54,6 +54,7 @@ class BlobRequester(object):
self._protocol_offers = {} self._protocol_offers = {}
self._price_disagreements = [] # [Peer] self._price_disagreements = [] # [Peer]
self._protocol_tries = {} self._protocol_tries = {}
self._maxed_out_peers = []
self._incompatible_peers = [] self._incompatible_peers = []
######## IRequestCreator ######### ######## IRequestCreator #########
@ -120,7 +121,9 @@ class BlobRequester(object):
def choose_best_peers(peers): def choose_best_peers(peers):
bad_peers = self._get_bad_peers() bad_peers = self._get_bad_peers()
return [p for p in peers if not p in bad_peers] without_bad_peers = [p for p in peers if not p in bad_peers]
without_maxed_out_peers = [p for p in without_bad_peers if p not in self._maxed_out_peers]
return without_maxed_out_peers
d.addCallback(choose_best_peers) d.addCallback(choose_best_peers)
@ -196,6 +199,10 @@ class RequestHelper(object):
def unavailable_blobs(self): def unavailable_blobs(self):
return self.requestor._unavailable_blobs[self.peer] return self.requestor._unavailable_blobs[self.peer]
@property
def maxed_out_peers(self):
return self.requestor._maxed_out_peers
def update_local_score(self, score): def update_local_score(self, score):
self.requestor._update_local_score(self.peer, score) self.requestor._update_local_score(self.peer, score)
@ -216,8 +223,16 @@ class RequestHelper(object):
return reason return reason
def get_and_save_rate(self): def get_and_save_rate(self):
if self.payment_rate_manager.price_limit_reached(self.peer):
if self.peer not in self.maxed_out_peers:
self.maxed_out_peers.append(self.peer)
return None
rate = self.protocol_prices.get(self.protocol) rate = self.protocol_prices.get(self.protocol)
if rate is None: if rate is None:
if self.peer in self.payment_rate_manager.strategy.pending_sent_offers:
pending = self.payment_rate_manager.strategy.pending_sent_offers[self.peer]
if not pending.is_too_low and not pending.is_accepted:
return pending.rate
rate = self.payment_rate_manager.get_rate_blob_data(self.peer, self.available_blobs) rate = self.payment_rate_manager.get_rate_blob_data(self.peer, self.available_blobs)
self.protocol_offers[self.protocol] = rate self.protocol_offers[self.protocol] = rate
return rate return rate
@ -343,7 +358,7 @@ class AvailabilityRequest(RequestHelper):
class PriceRequest(RequestHelper): class PriceRequest(RequestHelper):
"""Ask a peer if a certain price is acceptable""" """Ask a peer if a certain price is acceptable"""
def can_make_request(self): def can_make_request(self):
if self.requestor._available_blobs: if len(self.available_blobs) and not self.protocol in self.protocol_prices:
return self.get_and_save_rate() is not None return self.get_and_save_rate() is not None
return False return False
@ -373,14 +388,14 @@ class PriceRequest(RequestHelper):
assert self.protocol in self.protocol_offers assert self.protocol in self.protocol_offers
offer = Offer(self.protocol_offers[self.protocol]) offer = Offer(self.protocol_offers[self.protocol])
offer.handle(response_dict['blob_data_payment_rate']) offer.handle(response_dict['blob_data_payment_rate'])
self.payment_rate_manager.record_offer_reply(self.peer.host, offer) self.payment_rate_manager.record_offer_reply(self.peer, offer)
if offer.is_accepted: if offer.is_accepted:
log.info("Offered rate %f/mb accepted by %s", offer.rate, self.peer.host) log.info("Offered rate %f/mb accepted by %s", offer.rate, self.peer.host)
self.protocol_prices[self.protocol] = offer.rate self.protocol_prices[self.protocol] = offer.rate
return True return True
elif offer.is_too_low: elif offer.is_too_low:
log.debug("Offered rate %f/mb rejected by %s", offer.rate, self.peer.host) log.debug("Offered rate %f/mb rejected by %s", offer.rate, self.peer.host)
return True return not self.payment_rate_manager.price_limit_reached(self.peer)
else: else:
log.warning("Price disagreement") log.warning("Price disagreement")
self.requestor._price_disagreements.append(self.peer) self.requestor._price_disagreements.append(self.peer)