def test_jsbox_js_config_no_config(self): config = { 'jsbox_app_config': { } } self.assertEqual(utils.jsbox_js_config(config), {})
def get_jsbox_js_config(self, conv): try: return jsbox_js_config(conv.config) except Exception: log.err("Bad jsbox js config: %s" % (jsbox_config_value(conv.config, 'config'), )) return
def get_jsbox_js_config(self, conv): try: return jsbox_js_config(conv.config) except Exception: log.err( "Bad jsbox js config: %s" % (jsbox_config_value(conv.config, 'config'),)) return
def test_jsbox_js_config(self): config = { 'jsbox_app_config': { 'config': { 'key': 'config', 'value': json.dumps({'foo': 'bar'}) } } } self.assertEqual(utils.jsbox_js_config(config), {'foo': 'bar'})
def configured_endpoints(self, config): try: js_config = jsbox_js_config(config) except Exception: return [] # vumi-jssandbox-toolkit v2 endpoints try: v2_endpoints = list(js_config["endpoints"].keys()) except Exception: v2_endpoints = [] # vumi-jssandbox-toolkit v1 endpoints try: pool, tag = js_config["sms_tag"] v1_endpoints = [u"%s:%s" % (pool, tag)] except Exception: v1_endpoints = [] endpoints = v1_endpoints + v2_endpoints endpoints = [ep for ep in endpoints if isinstance(ep, unicode)] return sorted(set(endpoints))
def test_jsbox_js_config_no_config(self): config = {'jsbox_app_config': {}} self.assertEqual(utils.jsbox_js_config(config), {})
class JsBoxSendWorker(Worker): WORKER_QUEUE = DeferredQueue() stdout = sys.stdout stderr = sys.stderr JSBOX_CONFIG = { 'jsbox': lambda conv: jsbox_js_config(conv.config), 'dialogue': dialogue_js_config, } SUPPORTED_APPS = tuple(JSBOX_CONFIG.keys()) SEND_DELAY = 0.01 # No more than 100 msgs/second to the queue. def send_inbound_push_trigger(self, to_addr, conversation): self.emit('Starting %r [%s] -> %s' % (conversation.name, conversation.key, to_addr)) msg = mk_inbound_push_trigger(to_addr, conversation) return self.send_to_conv(conversation, msg) @inlineCallbacks def send_jsbox(self, user_account_key, conversation_key, hz=60, addr_exclude_path=None): conv = yield self.get_conversation(user_account_key, conversation_key) delivery_class = self.get_delivery_class(conv) excluded_addrs = self.get_excluded_addrs(addr_exclude_path) to_addrs = yield self.get_contact_addrs_for_conv( conv, delivery_class, excluded_addrs) ticker = Ticker(hz=hz) for i, to_addr in enumerate(to_addrs): yield self.send_inbound_push_trigger(to_addr, conv) if (i + 1) % 100 == 0: self.emit("Messages sent: %s / %s" % (i + 1, len(to_addrs))) yield ticker.tick() def get_delivery_class(self, conv): config_loader = self.JSBOX_CONFIG[conv.conversation_type] config = config_loader(conv) return config.get('delivery_class') def get_excluded_addrs(self, addr_exclude_path): if addr_exclude_path is None: return set() excluded_addrs = set() with open(addr_exclude_path, 'r') as exclude_file: for line in exclude_file.readlines(): line = line.strip() if line: excluded_addrs.add(line) return excluded_addrs @inlineCallbacks def get_contact_addrs_for_conv(self, conv, delivery_class, excluded_addrs): addrs = [] for contacts in (yield conv.get_opted_in_contact_bunches(delivery_class)): for contact in (yield contacts): addr = contact.addr_for(delivery_class) if addr not in excluded_addrs: addrs.append(addr) self.emit("Addresses collected: %s" % (len(addrs), )) returnValue(addrs) @inlineCallbacks def send_to_conv(self, conv, msg): publisher = self._publishers[conv.conversation_type] yield publisher.publish_message(msg) # Give the reactor time to actually send the message. yield deferLater(reactor, self.SEND_DELAY, lambda: None) @inlineCallbacks def make_publisher(self, conv_type): routing_key = '%s_transport.inbound' % (conv_type, ) self._publishers[conv_type] = yield self.publish_to(routing_key) @inlineCallbacks def get_conversation(self, user_account_key, conversation_key): user_api = self.vumi_api.get_user_api(user_account_key) conv = yield user_api.get_wrapped_conversation(conversation_key) if conv is None: raise ScriptError("Conversation not found: %s" % (conversation_key, )) if conv.conversation_type not in self.SUPPORTED_APPS: raise ScriptError("Unsupported conversation type: %s" % (conv.conversation_type, )) returnValue(conv) @inlineCallbacks def startWorker(self): self.vumi_api = yield VumiApi.from_config_async( self.config, self._amqp_client) self._publishers = {} for conv_type in self.SUPPORTED_APPS: yield self.make_publisher(conv_type) self.WORKER_QUEUE.put(self) def emit(self, obj, err=False): msg = '%s\n' % (obj, ) if err: self.stderr.write(msg) else: self.stdout.write(msg)