compacted.py (3084B)
1 import datetime 2 import os 3 from typing import List, Dict, Tuple, Union, Type 4 5 import boto3 6 from boto3.dynamodb.conditions import Key 7 8 from wow_token.db.trinity import Trinity 9 from wow_token.db.year_month import YearMonth 10 from wow_token.db.cache import Cache 11 from wow_token.region import Region 12 13 # TODO: Reduce Compacted Table Sprawl 14 15 REGION_MAP = { 16 'us-west-1': 'us-west-1', 17 'us-west-2': 'us-west-2', 18 'us-east-1': 'us-east-1', 19 'us-east-2': 'us-east-2', 20 'ap-south-1': 'eu-north-1', 21 'ap-northeast-3': 'ap-northeast-1', 22 'ap-northeast-2': 'ap-northeast-1', 23 'ap-southeast-1': 'ap-southeast-1', 24 'ap-southeast-2': 'ap-southeast-2', 25 'ap-northeast-1': 'ap-northeast-1', 26 'ca-central-1': 'us-east-1', 27 'eu-central-1': 'eu-north-1', 28 'eu-west-1': 'eu-west-1', 29 'eu-west-2': 'eu-west-1', 30 'eu-west-3': 'eu-west-3', 31 'eu-north-1': 'eu-north-1', 32 'sa-east-1': 'sa-east-1', 33 'eu-south-1': 'eu-north-1' 34 } 35 36 37 def _region_selector(): 38 if os.environ['AWS_REGION'] in REGION_MAP: 39 local_region = REGION_MAP[os.environ['AWS_REGION']] 40 else: 41 local_region = 'eu-central-1' 42 return local_region 43 44 45 def _data_as_str(data: List[Tuple[datetime.datetime, int]]) -> List[Tuple[str, int]]: 46 data_as_str = [] 47 for timestamp, price in data: 48 data_as_str.append((timestamp.isoformat(), price)) 49 return data_as_str 50 51 52 class Compacted: 53 _cache : Cache 54 def __init__(self): 55 self._ddb = boto3.resource('dynamodb', region_name=_region_selector()) 56 self._table = self._ddb.Table('wow-token-compacted') 57 self._cache = Cache(self) 58 59 def ddb_get_data(self, trinity: Trinity, _type: Union[Type[str], Type[datetime.datetime]] = datetime.datetime) -> Union[List[Tuple[datetime.datetime, int]], List[Tuple[str, int]]]: 60 data = [] 61 response = self._table.query( 62 KeyConditionExpression=Key('region-flavor-timestamp').eq(str(trinity)) 63 ) 64 if response['Items']: 65 for timestamp, price in response['Items'][0]['data'].items(): 66 date_time = datetime.datetime.fromtimestamp(int(timestamp), datetime.UTC) 67 if _type == str: 68 date_time = date_time.isoformat() 69 data.append(( 70 date_time, 71 int(price) 72 )) 73 return sorted(data, key=lambda x: x[0]) 74 75 def get_month(self, trinity: Trinity, _type: Union[Type[str], Type[datetime.datetime]] = datetime.datetime) -> Union[List[Tuple[datetime.datetime, int]], List[Tuple[str, int]]]: 76 if _type == str: 77 return _data_as_str(self._cache.get_month(trinity)) 78 return self._cache.get_month(trinity) 79 80 def get_precomputed_range(self, trinity: Trinity, _type: Union[Type[str], Type[datetime.datetime]] = datetime.datetime) -> Union[List[Tuple[datetime.datetime, int]], List[Tuple[str, int]]]: 81 if isinstance(trinity.range, YearMonth): 82 return self.get_month(trinity, _type=_type) 83 else: 84 return self.ddb_get_data(trinity, _type=_type)