# coding=utf-8 """""" from blinker.base import Namespace # pylint: disable=C0103 # invalid constant name ns = Namespace() #: sent when membership is set. Sender is community, arguments are: #: :class:`.models.Membership` instance, :bool:`is_new` membership_set = ns.signal("membership_set") #: sent just before membership is removed. Sender is community, arguments: # :class:`.models.Membership` instance membership_removed = ns.signal("membership_removed")
class LiveData(object): def __init__(self, pyrebase_app, root_path, ttl=None, retry_interval=None): self._app = pyrebase_app self._root_path = root_path self._ttl = ttl self._retry_interval = (RETRY_INTERVAL if retry_interval is None else retry_interval) self._db = self._app.database() self._streams = {} self._gc_streams = queue.Queue() self._gc_thread = None self._cache = None self.events = Namespace() self._handlers = { 'put': self._put_handler, 'patch': self._patch_handler, } def get_data(self): if self._cache is None: # Fetch data now value = self._db.child(self._root_path).get().val() self._cache = data.FirebaseData(value) # Listen for updates self.listen() return self._cache def get_data_silent(self): try: return self.get_data() except Exception: logger.exception('Error getting data') def set_data(self, path, value): path_list = data.get_path_list(path) child = self._db.child(self._root_path) for path_part in path_list: child = child.child(path_part) child.set(value) def is_stale(self): if self._ttl is None: return False data = self.get_data() if data is None or data.last_updated_at is None: logger.debug('Data is invalid: %s', data) return True stale = datetime.datetime.utcnow() - data.last_updated_at > self._ttl if stale: logger.debug('Data is stale: %s', data) else: logger.debug('Data is fresh: %s', data) return stale def signal(self, path, doc=None): norm_path = data.normalize_path(path) return self.events.signal(norm_path, doc=doc) def listen(self): stream = self._db.child(self._root_path).stream(self._stream_handler) self._streams[id(stream)] = stream self._start_stream_gc() watcher.watch(id(self), self.is_stale, self.restart, interval=self._ttl) # If the stream and stale watcher are established, # the metawatcher is no longer needed. self.cancel_metawatcher() def get_metawatcher_name(self): return 'meta_{}'.format(id(self)) def start_metawatcher(self): watcher.watch(self.get_metawatcher_name(), lambda: self._cache is None, self.get_data_silent, interval=self._retry_interval) def cancel_metawatcher(self): watcher.cancel(self.get_metawatcher_name()) def restart(self): self.reset() self.start_metawatcher() self.get_data_silent() def reset(self): logger.debug('Resetting all data') self.hangup(block=False) self._cache = None def hangup(self, block=True): logger.debug('Marking all streams for shut down') watcher.cancel(id(self)) for stream in self._streams.values(): self._gc_streams.put(stream) if block: self._gc_streams.join() def _set_path_value(self, path, value): data = self.get_data() data.set(path, value) self._recurse_signal(path) def _recurse_signal(self, path): path_list = data.get_path_list(path) partial_path = '' value = self.get_data() self.signal('/').send(value, value=value.get(), path=path) for part in path_list: partial_path = '/'.join((partial_path, part)) self.signal(partial_path).send(value, value=value.get(partial_path), path=path) def _put_handler(self, path, value): logger.debug('PUT: path=%s data=%s', path, value) self._set_path_value(path, value) def _patch_handler(self, path, all_values): logger.debug('PATCH: path=%s data=%s', path, all_values) for rel_path, value in all_values.items(): full_path = data.normalize_path('{}/{}'.format(path, rel_path)) self._set_path_value(full_path, value) def _valid_message(self, message): required_keys = [ 'event', 'path', 'data', ] valid_keys = all(k in message for k in required_keys) if not valid_keys: return False if message['event'] not in self._handlers: return False return True def _stream_handler(self, message): logger.debug('STREAM received: %s', message) if not self._valid_message(message): logger.warn('Invalid message: %s', message) return handler = self._handlers[message['event']] handler(message['path'], message['data']) def _gc_stream_worker(self): while True: stream = self._gc_streams.get() logger.debug('Closing stream: %s', stream) try: stream.close() del self._streams[id(stream)] except Exception as e: logger.warning('Error closing stream %s: %s', stream, e) else: logger.debug('Stream closed: %s', stream) self._gc_streams.task_done() def _start_stream_gc(self): if self._gc_thread is None: self._gc_thread = threading.Thread(target=self._gc_stream_worker, daemon=True) self._gc_thread.start()
Signals are the main tools used for decoupling applications components by sending notifications. In short, signals allow certain senders to notify subscribers that something happened. Cf. http://flask.pocoo.org/docs/signals/ for detailed documentation. The main signal is currently :obj:`activity`. """ from blinker.base import Namespace signals = Namespace() #: Triggered at application initialization when all extensions and plugins have #: been loaded components_registered = signals.signal("app:components:registered") #: Trigger when JS api must be registered. At this time :func:`flask.url_for` is #: usable register_js_api = signals.signal("app:register-js-api") #: This signal is used by the activity streams service and its clients. activity = signals.signal("activity") #: This signal is sent when user object has been loaded. g.user and current_user #: are available. user_loaded = signals.signal("user_loaded") auth_failed = signals.signal("auth_failed")
from blinker.base import Namespace SIG_ROLES_EDITED = 'roles-edited' SIG_ROLES_ADDED = 'roles-added' SIG_ACC_CREATED = 'acc-created' SIG_ACC_STATUS_CHANGE = 'acc-status-change' waitlist_bps = Namespace() roles_changed_sig = waitlist_bps.signal( SIG_ROLES_EDITED, "Called when roles are changed on an account") account_created_sig = waitlist_bps.signal( SIG_ACC_CREATED, 'Called when a new Waitlist Account is created') account_status_change_sig = waitlist_bps.signal( SIG_ACC_STATUS_CHANGE, 'Called when an account is enabled or disabled') roles_added_sig = waitlist_bps.signal(SIG_ROLES_ADDED, 'Called when a new role is added') def send_roles_changed(sender, to_id, by_id, added_roles, removed_roles, note): roles_changed_sig.send(sender, to_id=to_id, by_id=by_id, added_roles=added_roles, removed_roles=removed_roles, note=note) def send_roles_added(sender, by_id, role_name, role_display_name): roles_added_sig.send(sender, by_id=by_id, role_name=role_name,
# coding=utf-8 """""" from __future__ import absolute_import, print_function, unicode_literals from blinker.base import Namespace # pylint: disable=C0103 # invalid constant name ns = Namespace() #: sent when membership is set. Sender is community, arguments are: #: :class:`.models.Membership` instance, :bool:`is_new` membership_set = ns.signal("membership_set") #: sent just before membership is removed. Sender is community, arguments: # :class:`.models.Membership` instance membership_removed = ns.signal("membership_removed")
'Called when an account is enabled or disabled') role_created_sig = waitlist_bps.\ signal(SIG_ROLES_ADDED, 'Called when a new role is created') role_removed_sig = waitlist_bps.\ signal(SIG_ROLES_REMOVED, 'Called when a role is removed') alt_link_removed_sig = waitlist_bps.\ signal(SIG_ALT_LINK_REMOVED, 'Called when a link from an account to a character was removed') alt_link_added_sig = waitlist_bps.\ signal(SIG_ALT_LINK_ADDED, 'Called when a link from an account to a character was added') account_name_change_sig = waitlist_bps.signal( 'Called when the name of an account gets changed') def send_roles_changed(sender, to_id, by_id, added_roles, removed_roles, note): roles_changed_sig.send(sender, to_id=to_id, by_id=by_id, added_roles=added_roles, removed_roles=removed_roles, note=note) def send_role_created(sender, by_id, role_name, role_display_name): role_created_sig.send(sender, by_id=by_id, role_name=role_name,
subscribers that something happened. Cf. http://flask.pocoo.org/docs/signals/ for detailed documentation. The main signal is currently :obj:`activity`. """ from __future__ import absolute_import from blinker.base import Namespace signals = Namespace() #: Triggered at application initialization when all extensions and plugins have #: been loaded components_registered = signals.signal("app:components:registered") #: This signal is used by the activity streams service and its clients. activity = signals.signal("activity") #: Currently not used and subject to change. entity_created = signals.signal("entity:created") #: Currently not used and subject to change. entity_updated = signals.signal("entity:updated") #: Currently not used and subject to change. entity_deleted = signals.signal("entity:deleted") #user_created = signals.signal("user:created")
#!/usr/bin/env python # coding=utf8 __version__ = '0.5.dev1' from blinker.base import Namespace, Signal namespace = Namespace() user_id_changed = namespace.signal('user_id_changed') user_id_reset = namespace.signal('user_id_reset')
""" All signals used by Abilian Core. Cf. http://flask.pocoo.org/docs/signals/ for detailed documentation. These signals are currently not used, and for this reason subject to change. """ from blinker.base import Namespace signals = Namespace() entity_created = signals.signal("entity:created") entity_updated = signals.signal("entity:updated") entity_deleted = signals.signal("entity:deleted") #user_created = signals.signal("user:created") #user_deleted = signals.signal("user:deleted") activity = signals.signal("activity")
Signals are the main tools used for decoupling applications components by sending notifications. In short, signals allow certain senders to notify subscribers that something happened. Cf. http://flask.pocoo.org/docs/signals/ for detailed documentation. The main signal is currently :obj:`activity`. """ from __future__ import absolute_import, print_function, division from blinker.base import Namespace signals = Namespace() #: Triggered at application initialization when all extensions and plugins have #: been loaded components_registered = signals.signal("app:components:registered") #: Trigger when JS api must be registered. At this time :func:`flask.url_for` is #: usable register_js_api = signals.signal('app:register-js-api') #: This signal is used by the activity streams service and its clients. activity = signals.signal("activity") #: This signal is sent when user object has been loaded. g.user and current_user #: are available. user_loaded = signals.signal('user_loaded')
# coding=utf-8 """ """ from __future__ import absolute_import from blinker.base import Namespace # pylint: disable=C0103 # invalid constant name ns = Namespace() #: sent when membership is set. Sender is community, arguments are: #: :class:`.models.Membership` instance, :bool:`is_new` membership_set = ns.signal('membership_set') #: sent just before membership is removed. Sender is community, arguments: # :class:`.models.Membership` instance membership_removed = ns.signal('membership_removed')
Signals are the main tools used for decoupling applications components by sending notifications. In short, signals allow certain senders to notify subscribers that something happened. Cf. http://flask.pocoo.org/docs/signals/ for detailed documentation. The main signal is currently :obj:`activity`. """ from __future__ import absolute_import, division, print_function, \ unicode_literals from blinker.base import Namespace signals = Namespace() #: Triggered at application initialization when all extensions and plugins have #: been loaded components_registered = signals.signal("app:components:registered") #: Trigger when JS api must be registered. At this time :func:`flask.url_for` is #: usable register_js_api = signals.signal('app:register-js-api') #: This signal is used by the activity streams service and its clients. activity = signals.signal("activity") #: This signal is sent when user object has been loaded. g.user and current_user #: are available. user_loaded = signals.signal('user_loaded')