def ensure_funds(self, amount, bucket): res = super(BufferPaymentBackend, self).ensure_funds( amount=amount, bucket=bucket, ) if res: return True # Regular bucket didn't suffice - we need to use the buffer. name = task_to_name(bucket) budget = self.get_split_budget() budget_val = budget[name] if (budget_val >= amount): budget[name] = budget_val - amount self.job.jobpaymentsettings_set.filter(main=True).update( split_budget=budget, ) return True else: # We don't have enough funds in the appropriate bucket - we have # to take money from the buffer. amount = amount - budget_val buffer_free = budget[BUFFER_FREE_KEY_NAME] if buffer_free >= amount: # Transfer buffered funds to payment task's bucket. budget[name] = amount budget[BUFFER_FREE_KEY_NAME] = buffer_free - amount self.job.jobpaymentsettings_set.filter(main=True).update( split_budget=budget, ) return True return False
def split_budget(self, budget): """ Splits budget evenly on sample gathering, voting and btm. """ third = budget / 3.0 sample_gathering = third voting = third btm = budget - sample_gathering - voting budget = { task_to_name(JOB_TASK_SAMPLE_GATHERING): sample_gathering, self.get_free_budget_name(JOB_TASK_SAMPLE_GATHERING): sample_gathering, task_to_name(JOB_TASK_VOTING): voting, self.get_free_budget_name(JOB_TASK_VOTING): voting, task_to_name(JOB_TASK_BTM): btm, self.get_free_budget_name(JOB_TASK_BTM): btm, } return budget
def test_payment(self, job, worker, job_task, amount): name = task_to_name(job_task) + '-free' budget = self.get_split_budget() budget_val = budget[name] if (budget_val >= amount): return True else: # We don't have enough funds in the appropriate bucket - we have # to take money from the buffer. amount = amount - budget_val buffer_free = budget[BUFFER_FREE_KEY_NAME] return buffer_free >= amount
def issue_payment(self, payment, ensure_funds=True): """ Checks available funds in the appropriate bucket and buffer. If there are any available funds - they are removed from the pool of free resources. Return True on success. """ # Race condition here from direct payment issue and delayed payments # monitor. if not payment.is_initialized(): return False bucket_name = task_to_name(payment.job_task) + '-free' return self.ensure_funds(amount=payment.amount, bucket=bucket_name)
def issue_payment(self, payment, ensure_funds=True): """ Checks available funds in the appropriate bucket. If there are any available funds - they are removed from the pool of free resources. Return True on success. """ # Race condition here from direct payment issue and delayed payments # monitor. if not payment.is_initialized(): return False amount = payment.amount payments = self.job.workerpayment_set.filter(worker=payment.worker) if not payments.len(): # New worker res = super(MinimalPaymentBackend, self).issue_payment( payment=payment, ) if not res: return res bucket_name = task_to_name(payment.job_task) + '-free' return self.ensure_funds(amount=payment.amount, bucket=bucket_name)
def get_free_budget_name(self, task): return '%s-free' % task_to_name(task)