Skip to content

Instantly share code, notes, and snippets.

@minichate
Created April 8, 2020 16:44
Show Gist options
  • Save minichate/59fcbada1799bf35c65acf8ca14fdbb4 to your computer and use it in GitHub Desktop.
Save minichate/59fcbada1799bf35c65acf8ca14fdbb4 to your computer and use it in GitHub Desktop.
import datetime
from decimal import Decimal
import time
import random
INITIAL_RATES = {
"mandrill": Decimal("0.95"),
"sendgrid": Decimal("0.05"),
"sparkpost": Decimal("0"),
}
RATES = INITIAL_RATES.copy()
DECAY_RATE = Decimal("0.50")
RECOVER_RATE = Decimal("0.02")
LAST_TICK = datetime.datetime.now()
def decay(adaptor_key):
adaptor_rate = RATES[adaptor_key]
adjusted_rate = adaptor_rate * (1 - DECAY_RATE)
adjustment = adaptor_rate - adjusted_rate
remainder = Decimal(sum(RATES.values()) - RATES[adaptor_key])
for x in RATES:
if x == adaptor_key:
continue
weight = RATES[x] / remainder
RATES[x] = RATES[x] + (weight * adjustment)
RATES[adaptor_key] = adjusted_rate
def recover(adaptor_key):
difference = INITIAL_RATES[adaptor_key] - RATES[adaptor_key]
RATES[adaptor_key] = RATES[adaptor_key] + (RECOVER_RATE * difference)
def tick():
global LAST_TICK
for x in RATES:
recover(x)
LAST_TICK = datetime.datetime.now()
def randomly_select_adaptor():
probablility = random.uniform(0, 1)
cumulative_probability = Decimal("0.0")
for choice in RATES:
cumulative_probability += RATES[choice]
if probablility < cumulative_probability:
break
return choice
def _example_random_mandrill_error():
if randomly_select_adaptor() == "mandrill":
print("ERROR")
decay("mandrill")
while True:
tick_delta = datetime.datetime.now() - LAST_TICK
if tick_delta > datetime.timedelta(seconds=1):
tick()
time.sleep(0.1)
print(RATES)
# Simulate a mandrill outage
# Everytime mandril is the "chosen" adaptor, it errors
_example_random_mandrill_error()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment