import datetime import os from typing import List, Dict, Tuple, Union, Type import boto3 from boto3.dynamodb.conditions import Key from wow_token.db.trinity import Trinity from wow_token.db.year_month import YearMonth from wow_token.db.cache import Cache from wow_token.region import Region # TODO: Reduce Compacted Table Sprawl REGION_MAP = { 'us-west-1': 'us-west-1', 'us-west-2': 'us-west-2', 'us-east-1': 'us-east-1', 'us-east-2': 'us-east-2', 'ap-south-1': 'eu-north-1', 'ap-northeast-3': 'ap-northeast-1', 'ap-northeast-2': 'ap-northeast-1', 'ap-southeast-1': 'ap-southeast-1', 'ap-southeast-2': 'ap-southeast-2', 'ap-northeast-1': 'ap-northeast-1', 'ca-central-1': 'us-east-1', 'eu-central-1': 'eu-north-1', 'eu-west-1': 'eu-west-1', 'eu-west-2': 'eu-west-1', 'eu-west-3': 'eu-west-3', 'eu-north-1': 'eu-north-1', 'sa-east-1': 'sa-east-1', 'eu-south-1': 'eu-north-1' } def _region_selector(): if os.environ['AWS_REGION'] in REGION_MAP: local_region = REGION_MAP[os.environ['AWS_REGION']] else: local_region = 'eu-central-1' return local_region def _data_as_str(data: List[Tuple[datetime.datetime, int]]) -> List[Tuple[str, int]]: data_as_str = [] for timestamp, price in data: data_as_str.append((timestamp.isoformat(), price)) return data_as_str class Compacted: _cache : Cache def __init__(self): self._ddb = boto3.resource('dynamodb', region_name=_region_selector()) self._table = self._ddb.Table('wow-token-compacted') self._cache = Cache(self) 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]]]: data = [] response = self._table.query( KeyConditionExpression=Key('region-flavor-timestamp').eq(str(trinity)) ) if response['Items']: for timestamp, price in response['Items'][0]['data'].items(): date_time = datetime.datetime.fromtimestamp(int(timestamp), datetime.UTC) if _type == str: date_time = date_time.isoformat() data.append(( date_time, int(price) )) return sorted(data, key=lambda x: x[0]) 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]]]: if _type == str: return _data_as_str(self._cache.get_month(trinity)) return self._cache.get_month(trinity) 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]]]: if isinstance(trinity.range, YearMonth): return self.get_month(trinity, _type=_type) else: return self.ddb_get_data(trinity, _type=_type)