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:
parent
a9ae1a1016
commit
ea21821558
3 changed files with 35 additions and 10 deletions
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue