Philip/ussd poler
This commit is contained in:
@@ -31,7 +31,8 @@ from cic_ussd.cache import cache_data_key, cache_data, get_cached_data
|
||||
from cic_ussd.db.models.account import Account
|
||||
from cic_ussd.metadata import PersonMetadata
|
||||
from cic_ussd.phone_number import Support
|
||||
from cic_ussd.processor.util import parse_person_metadata, ussd_menu_list, wait_for_session_data
|
||||
from cic_ussd.processor.poller import wait_for_session_data
|
||||
from cic_ussd.processor.util import parse_person_metadata, ussd_menu_list
|
||||
from cic_ussd.session.ussd_session import save_session_data
|
||||
from cic_ussd.state_machine.logic.language import preferred_langauge_from_selection
|
||||
from cic_ussd.translation import translation_for
|
||||
|
||||
104
apps/cic-ussd/cic_ussd/processor/poller.py
Normal file
104
apps/cic-ussd/cic_ussd/processor/poller.py
Normal file
@@ -0,0 +1,104 @@
|
||||
# standard imports
|
||||
import logging
|
||||
import time
|
||||
from queue import Queue
|
||||
from typing import Callable, Dict, Optional, Tuple, Union
|
||||
|
||||
# external imports
|
||||
from cic_types.condiments import MetadataPointer
|
||||
|
||||
# local imports
|
||||
from cic_ussd.cache import cache_data_key, get_cached_data
|
||||
from cic_ussd.error import MaxRetryReached
|
||||
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
# adapted from https://github.com/justiniso/polling/blob/master/polling.py
|
||||
# opted not to use the package to reduce dependency
|
||||
def poller(args: Optional[Tuple],
|
||||
interval: int,
|
||||
kwargs: Optional[Dict],
|
||||
max_retry: int,
|
||||
target: Callable[..., Union[Dict, str]]):
|
||||
""""""
|
||||
collected_values: list = []
|
||||
expected_value = None
|
||||
tries = 0
|
||||
|
||||
while True:
|
||||
if tries >= max_retry:
|
||||
raise MaxRetryReached(collected_values, expected_value)
|
||||
try:
|
||||
if args:
|
||||
value = target(*args)
|
||||
elif kwargs:
|
||||
value = target(**kwargs)
|
||||
else:
|
||||
value = target()
|
||||
expected_value = value
|
||||
except () as error:
|
||||
expected_value = error
|
||||
else:
|
||||
if bool(value) or value == {}:
|
||||
logg.debug(f'Resource: {expected_value} now available.')
|
||||
break
|
||||
collected_values.append(expected_value)
|
||||
logg.debug(f'Collected values are: {collected_values}')
|
||||
tries += 1
|
||||
time.sleep(interval)
|
||||
|
||||
|
||||
def wait_for_cache(identifier: Union[list, bytes],
|
||||
resource_name: str,
|
||||
salt: MetadataPointer,
|
||||
interval: int = 1,
|
||||
max_retry: int = 5):
|
||||
"""
|
||||
:param identifier:
|
||||
:type identifier:
|
||||
:param interval:
|
||||
:type interval:
|
||||
:param resource_name:
|
||||
:type resource_name:
|
||||
:param salt:
|
||||
:type salt:
|
||||
:param max_retry:
|
||||
:type max_retry:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
key: str = cache_data_key(identifier=identifier, salt=salt)
|
||||
logg.debug(f'Polling for resource: {resource_name} at: {key} every: {interval} second(s) for {max_retry} seconds.')
|
||||
poller(args=(key,), interval=interval, kwargs=None, max_retry=max_retry, target=get_cached_data)
|
||||
|
||||
|
||||
def wait_for_session_data(resource_name: str,
|
||||
session_data_key: str,
|
||||
ussd_session: dict,
|
||||
interval: int = 1,
|
||||
max_retry: int = 5):
|
||||
"""
|
||||
:param interval:
|
||||
:type interval:
|
||||
:param resource_name:
|
||||
:type resource_name:
|
||||
:param session_data_key:
|
||||
:type session_data_key:
|
||||
:param ussd_session:
|
||||
:type ussd_session:
|
||||
:param max_retry:
|
||||
:type max_retry:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
# poll for data element first
|
||||
logg.debug(f'Data poller with max retry at: {max_retry}. Checking for every: {interval} seconds.')
|
||||
poller(args=('data',), interval=interval, kwargs=None, max_retry=max_retry, target=ussd_session.get)
|
||||
|
||||
# poll for session data element
|
||||
get_session_data = ussd_session.get('data').get
|
||||
logg.debug(f'Session data poller for: {resource_name} with max retry at: {max_retry}. Checking for every: {interval} seconds.')
|
||||
poller(args=(session_data_key,), interval=interval, kwargs=None, max_retry=max_retry, target=get_session_data)
|
||||
|
||||
@@ -102,77 +102,3 @@ def ussd_menu_list(fallback: str, menu_list: list, split: int = 3) -> List[str]:
|
||||
except IndexError:
|
||||
menu_list_reprs.append(fallback)
|
||||
return menu_list_reprs
|
||||
|
||||
|
||||
def wait_for_cache(identifier: Union[list, bytes], resource_name: str, salt: MetadataPointer, interval: int = 1, max_retry: int = 5):
|
||||
"""
|
||||
:param identifier:
|
||||
:type identifier:
|
||||
:param interval:
|
||||
:type interval:
|
||||
:param resource_name:
|
||||
:type resource_name:
|
||||
:param salt:
|
||||
:type salt:
|
||||
:param max_retry:
|
||||
:type max_retry:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
key = cache_data_key(identifier=identifier, salt=salt)
|
||||
resource = get_cached_data(key)
|
||||
counter = 0
|
||||
while resource is None:
|
||||
logg.debug(f'Waiting for: {resource_name} at: {key}. Checking after: {interval} ...')
|
||||
time.sleep(interval)
|
||||
counter += 1
|
||||
resource = get_cached_data(key)
|
||||
if resource is not None:
|
||||
logg.debug(f'{resource_name} now available.')
|
||||
break
|
||||
else:
|
||||
if counter == max_retry:
|
||||
logg.debug(f'Could not find: {resource_name} within: {max_retry}')
|
||||
break
|
||||
|
||||
|
||||
def wait_for_session_data(resource_name: str, session_data_key: str, ussd_session: dict, interval: int = 1, max_retry: int = 5):
|
||||
"""
|
||||
:param interval:
|
||||
:type interval:
|
||||
:param resource_name:
|
||||
:type resource_name:
|
||||
:param session_data_key:
|
||||
:type session_data_key:
|
||||
:param ussd_session:
|
||||
:type ussd_session:
|
||||
:param max_retry:
|
||||
:type max_retry:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
data = ussd_session.get('data')
|
||||
data_poller = 0
|
||||
while not data:
|
||||
logg.debug(f'Waiting for data object on ussd session: {ussd_session.get("external_session_id")}')
|
||||
logg.debug(f'Data poller at: {data_poller}. Checking again after: {interval} secs...')
|
||||
time.sleep(interval)
|
||||
data_poller += 1
|
||||
if data:
|
||||
logg.debug(f'Data object found, proceeding to poll for: {session_data_key}')
|
||||
break
|
||||
if data:
|
||||
session_data_poller = 0
|
||||
session_data = data.get(session_data_key)
|
||||
while not session_data_key:
|
||||
logg.debug(
|
||||
f'Session data poller at: {data_poller} with max retry at: {max_retry}. Checking again after: {interval} secs...')
|
||||
time.sleep(interval)
|
||||
session_data_poller += 1
|
||||
|
||||
if session_data:
|
||||
logg.debug(f'{resource_name} now available.')
|
||||
break
|
||||
|
||||
elif session_data_poller >= max_retry:
|
||||
logg.debug(f'Could not find data object within: {max_retry}')
|
||||
|
||||
Reference in New Issue
Block a user