class SettingStorage(object): # def __init__(self, *args, topic='storage', connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.__topic = topic self.__default_key = ':'.join([self.__connector.CHANNEL_GROUP, self.__topic]) # super(SettingStorage, self).__init__() # ## @property def connector(self): return self.__connector # ## def get(self, key:str): value = self.__open_connection().get(self.__gen_absolute_key(key)) if isinstance(value, bytes): value = value.decode('utf-8') if isinstance(value, str): obj, err = json_loads(value) if err: raise err return obj return value # ## def store(self, key:str, obj:Union[dict,list,str,float,int,bool]): value, err = json_dumps(obj) if err: raise err return self.__open_connection().set(self.__gen_absolute_key(key), value) # ## def clear(self, key:str): return self.__open_connection().delete(self.__gen_absolute_key(key)) # ## def close(self): if not self.__use_shared_connector: self.__connector.close() if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "SettingStorage has closed") # # def __open_connection(self): return assure_not_null(self.__connector.rewind().connect(pinging=False, retrying=False)) # def __gen_absolute_key(self, key): if key: return self.__default_key + ':' + str(key) return self.__default_key
def __init__(self, *args, connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.CHANNEL_PREFIX = self.__connector.CHANNEL_GROUP + ':' # super(SettingPublisher, self).__init__()
def __init__(self, topic='counter', connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.__topic = topic self.__default_key = ':'.join([self.__connector.CHANNEL_GROUP, self.__topic]) # super(AutoIncrement, self).__init__()
def __init__(self, *args, topic='storage', connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.__topic = topic self.__default_key = ':'.join([self.__connector.CHANNEL_GROUP, self.__topic]) # super(SettingStorage, self).__init__()
def __init__(self, *args, connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.__transformer = transform_json_data # self.CHANNEL_PATTERN = self.__connector.CHANNEL_GROUP + '*' # super(SettingSubscriber, self).__init__()
class AutoIncrement(object): # def __init__(self, topic='counter', connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.__topic = topic self.__default_key = ':'.join([self.__connector.CHANNEL_GROUP, self.__topic]) # super(AutoIncrement, self).__init__() # ## @property def connector(self): return self.__connector # ## def init(self, label:Optional[str]=None, value:Optional[int]=0): return self.__open_connection().set(self.__gen_absolute_key(label), value, nx=True) # ## def incr(self, label:Optional[str]=None, amount:Optional[int]=1): return self.__open_connection().incr(self.__gen_absolute_key(label), amount=amount) # # def clear(self, label:Optional[str]=None): return self.__open_connection().delete(self.__gen_absolute_key(label)) # # def reset(self, label:Optional[str]=None, value:Optional[int]=0): return self.__open_connection().set(self.__gen_absolute_key(label), value) # # def close(self): if not self.__use_shared_connector: self.__connector.close() if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "AutoIncrement has closed") # # def __open_connection(self): return assure_not_null(self.__connector.rewind().connect(pinging=False, retrying=False)) # def __gen_absolute_key(self, label): if label: return self.__default_key + ':' + str(label) return self.__default_key
class SettingSubscriber(object): # def __init__(self, *args, connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.__transformer = transform_json_data # self.CHANNEL_PATTERN = self.__connector.CHANNEL_GROUP + '*' # super(SettingSubscriber, self).__init__() # ## @property def connector(self): return self.__connector # ## @property def pubsub(self): ps = assure_not_null(self.__connector.connect()).pubsub() ps.psubscribe(**{self.CHANNEL_PATTERN: self.__process_event}) return ps # ## __pubsub_thread = None __pubsub_lock = threading.RLock() # def start(self): with self.__pubsub_lock: if self.__pubsub_thread is None: self.__pubsub_thread = self.__run_in_thread(sleep_time=0.001) if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "SettingSubscriber has started") return self.__pubsub_thread # def stop(self): return self.close() # def close(self): with self.__pubsub_lock: if self.__pubsub_thread is not None: self.__pubsub_thread.stop() # if not self.__use_shared_connector: self.__connector.close() # if self.__pubsub_thread is not None: self.__pubsub_thread.join() self.__pubsub_thread = None # if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "SettingSubscriber has stopped") # # def __run_in_thread(self, auto_start=True, sleep_time=0, daemon=False): thread = PubSubWorkerThread(self, sleep_time, daemon=daemon) if auto_start: thread.start() return thread # ## __transformer: Optional[Callable[[Dict], Tuple[Dict, Any]]] = None # def set_transformer(self, transformer: Callable[[Dict], Tuple[Dict, Any]]): if callable(transformer): self.__transformer = transformer return self # ## __event_mappings: Optional[Dict[Callable[[Dict, Any], bool], Tuple[Callable[[Dict, Any], None],...]]] = None # def add_event_handler(self, match: Callable[[Dict, Any], bool], *reset: Callable[[Dict, Any], None]): if self.__event_mappings is None: self.__event_mappings = dict() if not callable(match): raise ValueError('[match] must be callable') if not reset: raise ValueError('[reset] list must not be empty') for i, func in enumerate(reset): if not callable(func): raise ValueError('function#{0} must be callable'.format(i)) self.__event_mappings[match] = reset return self # def __process_event(self, message): if self.__event_mappings is None: if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "handler_mappings is empty (no service has been registered yet)") return # if self.__transformer is not None: msg, err = self.__transformer(message) else: msg, err = (message, None) # for match, reaction in self.__event_mappings.items(): if match(msg, err): if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "the matching function [{0}] is matched".format(match.__name__)) for reset in reaction: if callable(reset): if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "the handler [{0}] is triggered".format(reset.__name__)) reset(msg, err) # # def register_receiver(self, capsule: SettingCapsule): def wrap_capsule_reset(message, err): return capsule.reset(parameters=extract_parameters(message, err)) if isinstance(capsule, SettingCapsule): self.add_event_handler(match_by_label(capsule.label), wrap_capsule_reset) return capsule
class SettingPublisher(object): # def __init__(self, *args, connector=None, **kwargs): if isinstance(connector, RedisClient): self.__use_shared_connector = True self.__connector = connector else: self.__use_shared_connector = False self.__connector = RedisClient(**kwargs) # self.CHANNEL_PREFIX = self.__connector.CHANNEL_GROUP + ':' # super(SettingPublisher, self).__init__() # ## @property def connector(self): return self.__connector # ## def publish(self, message: Union[Dict, bytes, str, int, float], label: Optional[Union[bytes, str]] = None, with_datetime: Optional[bool] = False, raise_on_error: Optional[bool] = False) -> Optional[Exception]: try: self.__publish_or_error(message, label=label, with_datetime=with_datetime) return None except Exception as err: if raise_on_error: raise err return err # # def __publish_or_error(self, message, label=None, with_datetime=False): if label is None: channel_name = self.__connector.CHANNEL_GROUP else: if isinstance(label, bytes): label = label.decode('utf-8') else: label = str(label) channel_name = self.CHANNEL_PREFIX + label # if isinstance(message, (dict, list)): message, err = json_dumps(message, with_datetime=with_datetime) if err: if LOG.isEnabledFor(logging.ERROR): LOG.log(logging.ERROR, err) raise err elif not self.__is_valid_type(message): errmsg = "Invalid type of input: '%s'. Only a dict, list, bytes, string, int or float accepted." % type( message) if LOG.isEnabledFor(logging.ERROR): LOG.log(logging.ERROR, errmsg) raise ValueError(errmsg) # if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "publish() a message [%s] to channel [%s]", str(message), channel_name) # self.__open_connection().publish(channel_name, message) # # def close(self): if not self.__use_shared_connector: self.__connector.close() if LOG.isEnabledFor(logging.DEBUG): LOG.log(logging.DEBUG, "SettingPublisher has closed") # # def __open_connection(self): return assure_not_null(self.__connector.rewind().connect( pinging=False, retrying=False)) # # @staticmethod def __is_valid_type(data): return isinstance(data, (bytes, str, float)) or (isinstance(data, int) and (type(data) != type(True)))
#!/usr/bin/env python3 import __init__ from datetime import datetime from configator.engine.connector import RedisClient from configator.engine import SettingSubscriber from configator.utils.function_util import match_by_label, transform_json_data from configator.utils.signal_util import hook_signal #------------------------------------------------------------------------------ c = RedisClient() #------------------------------------------------------------------------------ def trigger1(message, *args, **kwargs): print('1. clear the config') def trigger2(message, *args, **kwargs): print('2. update the config: %s' % str(message)) def trigger3(message, *args, **kwargs): print('3. reset the engine') print()