def _publish_message(self, message, endpoint_name=None): if not self.get_metadata_helper(message).get_conversation_info: log.error( "Conversation metadata missing for message for %s: %s" % ( type(self).__name__, message)) return super(GoApplicationWorker, self)._publish_message( message, endpoint_name)
def handle_outbound_message_failure(self, f, message): """ Handle outbound message failures. `ServiceException`, `PolicyException` and client-class SOAP faults result in `PermanentFailure` being raised; server-class SOAP faults instances result in `TemporaryFailure` being raised; and other failures are passed through. """ log.error(f, 'Sending SMS failure on ParlayX: %r' % ( self.transport_name,)) if not f.check(ServiceException, PolicyException): if f.check(SoapFault): # We'll give server-class unknown SOAP faults the benefit of # the doubt as far as temporary failures go. if f.value.code.endswith('Server'): raise TemporaryFailure(f) yield self.publish_nack(message['message_id'], f.getErrorMessage()) if f.check(SoapFault): # We've ruled out unknown SOAP faults, so this must be a permanent # failure. raise PermanentFailure(f) returnValue(f)
def _process_message(self, message, direction): namespace = self.namespace_handler(message) if namespace is None: log.error(SessionLengthMiddlewareError( "Session length redis namespace cannot be None, " "skipping message")) returnValue(message) key_addr = self._key_address(message, direction) if key_addr is None: log.error(SessionLengthMiddlewareError( "Session length key address cannot be None, " "skipping message")) returnValue(message) redis_key = self._key(namespace, key_addr) if message.get('session_event') == self.SESSION_NEW: yield self._handle_start(message, redis_key) elif message.get('session_event') == self.SESSION_CLOSE: yield self._handle_end(message, redis_key) else: yield self._handle_default(message, redis_key) returnValue(message)
def handle_outbound_message(self, message): if message.payload.get('in_reply_to'): should_close = (message['session_event'] == TransportUserMessage.SESSION_CLOSE) response_data = { "shouldClose": should_close, "ussdMenu": message.get('content'), "responseExitCode": 200, "responseMessage": "", } response_id = self.finish_request(message['in_reply_to'], json.dumps(response_data)) if response_id is None: err_msg = ("Infobip transport could not find original request" " when attempting to reply.") log.error(InfobipError(err_msg)) return self.publish_nack(user_message_id=message['message_id'], reason=err_msg) else: return self.publish_ack(message['message_id'], sent_message_id=response_id) else: err_msg = ("Infobip transport cannot process outbound message that" " is not a reply: %s" % (message['message_id'],)) log.error(InfobipError(err_msg)) return self.publish_nack(user_message_id=message['message_id'], reason=err_msg)
def _process_message(self, message, direction): namespace = self.namespace_handler(message) if namespace is None: log.error( SessionLengthMiddlewareError( "Session length redis namespace cannot be None, " "skipping message")) returnValue(message) key_addr = self._key_address(message, direction) if key_addr is None: log.error( SessionLengthMiddlewareError( "Session length key address cannot be None, " "skipping message")) returnValue(message) redis_key = self._key(namespace, key_addr) if message.get('session_event') == self.SESSION_NEW: yield self._handle_start(message, redis_key) elif message.get('session_event') == self.SESSION_CLOSE: yield self._handle_end(message, redis_key) else: yield self._handle_default(message, redis_key) returnValue(message)
def consume_control_command(self, cmd): worker_name = cmd.get('worker_name') publisher = self.worker_publishers.get(worker_name) if publisher: yield publisher.publish_message(cmd) log.info('Sent %s to %s' % (cmd, worker_name)) else: log.error('No worker publisher available for %s' % (cmd, ))
def consume_control_command(self, cmd): worker_name = cmd.get('worker_name') publisher = self.worker_publishers.get(worker_name) if publisher: yield publisher.publish_message(cmd) log.info('Sent %s to %s' % (cmd, worker_name)) else: log.error('No worker publisher available for %s' % (cmd,))
def dispatch_outbound_message(self, msg): transport_name = msg['transport_name'] redirect_to = self.outbound_mappings.get(transport_name) if redirect_to: self.dispatcher.publish_outbound_message(redirect_to, msg) else: log.error(DispatcherError( 'No redirect_outbound specified for %s' % ( transport_name,)))
def dispatch_outbound_message(self, msg): name = msg['transport_name'] name = self.config.get('transport_mappings', {}).get(name, name) if name in self.dispatcher.transport_publisher: self.dispatcher.publish_outbound_message(name, msg) else: log.error( DispatcherError('Unknown transport_name: %s, discarding %r' % (name, msg.payload)))
def dispatch_outbound_message(self, msg): transport_name = msg['transport_name'] redirect_to = self.outbound_mappings.get(transport_name) if redirect_to: self.dispatcher.publish_outbound_message(redirect_to, msg) else: log.error( DispatcherError('No redirect_outbound specified for %s' % (transport_name, )))
def _process_request_results(self, results): for success, result in results: if not success: # errors here are bugs in Vumi and thus should always # be logged via Twisted too. log.error(result) # we log them again in a simplified form via the sandbox # api so that the sandbox owner gets to see them too self.api.log(result.getErrorMessage(), logging.ERROR)
def dispatch_outbound_message(self, msg): name = msg['transport_name'] name = self.config.get('transport_mappings', {}).get(name, name) if name in self.dispatcher.transport_publisher: self.dispatcher.publish_outbound_message(name, msg) else: log.error(DispatcherError( 'Unknown transport_name: %s, discarding %r' % ( name, msg.payload)))
def dispatch_outbound_message(self, msg): transport_name = self.transport_mappings.get(msg['from_addr']) if transport_name is not None: self.publish_transport(transport_name, msg) message_key = self.get_message_key(msg['message_id']) self.r_server.set(message_key, msg['transport_name']) yield self.r_server.expire(message_key, self.expire_routing_timeout) else: log.error("No transport for %s" % (msg['from_addr'], ))
def dispatch_outbound_message(self, msg): transport_name = self.transport_mappings.get(msg['from_addr']) if transport_name is not None: self.publish_transport(transport_name, msg) message_key = self.get_message_key(msg['message_id']) self.r_server.set(message_key, msg['transport_name']) yield self.r_server.expire(message_key, self.expire_routing_timeout) else: log.error("No transport for %s" % (msg['from_addr'],))
def dispatch_inbound_event(self, msg): message_key = self.get_message_key(msg['user_message_id']) name = self.r_server.get(message_key) if not name: log.error("No transport_name for return route found in Redis" " while dispatching transport event for message %s" % (msg['user_message_id'], )) try: self.publish_exposed_event(name, msg) except: log.error("No publishing route for %s" % (name, ))
def dispatch_inbound_event(self, msg): message_key = self.get_message_key(msg['user_message_id']) name = self.r_server.get(message_key) if not name: log.error("No transport_name for return route found in Redis" " while dispatching transport event for message %s" % (msg['user_message_id'],)) try: self.publish_exposed_event(name, msg) except: log.error("No publishing route for %s" % (name,))
def find_inboundmessage_for_reply(self, reply): user_message_id = reply.get('in_reply_to') if user_message_id is None: log.error('Received reply without in_reply_to: %s' % (reply,)) return msg = yield self.vumi_api.mdb.inbound_messages.load(user_message_id) if msg is None: log.error('Unable to find message for reply: %s' % (reply,)) returnValue(msg)
def handle_decode_error(self, message_id, request): req = self.get_request_dict(request) log.error('Bad request encoding: %r' % req) self.respond(message_id, http.BAD_REQUEST, {'invalid_request': req}) yield self.add_status( component='inbound', status='down', type='request_decode_error', message='Bad request encoding', details={'request': req})
def find_inboundmessage_for_reply(self, reply): user_message_id = reply.get('in_reply_to') if user_message_id is None: log.error('Received reply without in_reply_to: %s' % (reply, )) return msg = yield self.vumi_api.mdb.inbound_messages.load(user_message_id) if msg is None: log.error('Unable to find message for reply: %s' % (reply, )) returnValue(msg)
def dispatch_outbound_message(self, msg): yield self._redis_d # Horrible hack to ensure we have it setup. transport_name = self.transport_mappings.get(msg['from_addr']) if transport_name is not None: self.publish_transport(transport_name, msg) message_key = self.get_message_key(msg['message_id']) yield self.session_manager.create_session( message_key, name=msg['transport_name']) else: log.error(DispatcherError( "No transport for %s" % (msg['from_addr'],)))
def find_outboundmessage_for_event(self, event): user_message_id = event.get('user_message_id') if user_message_id is None: log.error('Received event without user_message_id: %s' % (event, )) return msg = yield self.vumi_api.mdb.outbound_messages.load(user_message_id) if msg is None: log.error('Unable to find message for event: %s' % (event, )) returnValue(msg)
def get_provider(self, addr): if addr is None: log.error(ProviderSettingMiddlewareError( "Address for determining message provider cannot be None," " skipping message")) return None addr = self.normalize_addr(addr) for prefix, provider in self.provider_prefixes: if addr.startswith(prefix): return provider return None
def dispatch_outbound_message(self, msg): yield self._redis_d # Horrible hack to ensure we have it setup. transport_name = self.transport_mappings.get(msg['from_addr']) if transport_name is not None: self.publish_transport(transport_name, msg) message_key = self.get_message_key(msg['message_id']) yield self.session_manager.create_session( message_key, name=msg['transport_name']) else: log.error( DispatcherError("No transport for %s" % (msg['from_addr'], )))
def find_outboundmessage_for_event(self, event): user_message_id = event.get('user_message_id') if user_message_id is None: log.error('Received event without user_message_id: %s' % (event,)) return msg = yield self.vumi_api.mdb.outbound_messages.load(user_message_id) if msg is None: log.error('Unable to find message for event: %s' % (event,)) returnValue(msg)
def get_provider(self, addr): if addr is None: log.error( ProviderSettingMiddlewareError( "Address for determining message provider cannot be None," " skipping message")) return None addr = self.normalize_addr(addr) for prefix, provider in self.provider_prefixes: if addr.startswith(prefix): return provider return None
def dispatch_inbound_message(self, msg): keyword = get_first_word(msg['content']).lower() matched = False for rule in self.rules: if self.is_msg_matching_routing_rules(keyword, msg, rule): matched = True self.publish_exposed_inbound(rule['app'], msg) if not matched: if self.fallback_application is not None: self.publish_exposed_inbound(self.fallback_application, msg) else: log.error('Message could not be routed: %r' % (msg, ))
def dispatch_inbound_message(self, msg): keyword = get_first_word(msg['content']).lower() matched = False for rule in self.rules: if self.is_msg_matching_routing_rules(keyword, msg, rule): matched = True self.publish_exposed_inbound(rule['app'], msg) if not matched: if self.fallback_application is not None: self.publish_exposed_inbound(self.fallback_application, msg) else: log.error('Message could not be routed: %r' % (msg,))
def dispatch_inbound_event(self, msg): yield self._redis_d # Horrible hack to ensure we have it setup. message_key = self.get_message_key(msg['user_message_id']) session = yield self.session_manager.load_session(message_key) name = session.get('name') if not name: log.error(DispatcherError( "No transport_name for return route found in Redis" " while dispatching transport event for message %s" % (msg['user_message_id'],))) try: self.publish_exposed_event(name, msg) except: log.error(DispatcherError("No publishing route for %s" % (name,)))
def log(self, msg, level='msg'): timezone = None local_time = self.get_local_time() rkey = "%slogs" % (self.r_prefix, ) self.r_server.zremrangebyscore( rkey, 1, get_local_time_as_timestamp(local_time - timedelta(hours=2))) self.r_server.zadd( rkey, "[%s] %s" % (time_to_vusion_format(local_time), msg), get_local_time_as_timestamp(local_time)) if (level == 'msg'): log.msg('[%s] %s' % (self.control_name, msg)) else: log.error('[%s] %s' % (self.control_name, msg))
def handle_event(self, event): message = yield self.find_message_for_event(event) if message is None: log.error('Unable to find message for %s, user_message_id: %s' % ( event['event_type'], event.get('user_message_id'))) return msg_mdh = self.get_metadata_helper(message) conv = yield msg_mdh.get_conversation() if conv: window_id = self.get_window_id(conv.key, conv.batch.key) flight_key = yield self.window_manager.get_internal_id(window_id, message['message_id']) yield self.window_manager.remove_key(window_id, flight_key)
def receive_control_message(self, msg): log.debug('Received control! %s' % (msg, )) try: if msg['message_type'] == 'add_worker': if msg['worker_name'] in self.workers: log.error('Cannot create worker, name already exist: %s' % (msg['worker_name'], )) return for key in msg['config'].keys(): msg['config'][key] = msg['config'][key].encode('utf-8') self.config[msg['worker_name']] = msg['config'] worker = self.create_worker(msg['worker_name'], msg['worker_class']) self.workers[msg['worker_name']] = worker if msg['message_type'] == 'remove_worker': if not msg['worker_name'] in self.workers: log.error('Cannot remove worker, name unknown: %s' % (msg['worker_name'])) return yield self.workers[msg['worker_name']].stopService() self.workers[msg['worker_name']].disownServiceParent() self.workers.pop(msg['worker_name']) except Exception as ex: log.error("Control received: %s" % (msg)) log.error("Unexpected error %s" % repr(ex))
def receive_control_message(self, msg): log.debug('Received control! %s' % (msg,)) try: if msg['message_type'] == 'add_worker': if msg['worker_name'] in self.workers: log.error('Cannot create worker, name already exist: %s' % (msg['worker_name'],)) return for key in msg['config'].keys(): msg['config'][key] = msg['config'][key].encode('utf-8') self.config[msg['worker_name']] = msg['config'] worker = self.create_worker(msg['worker_name'], msg['worker_class']) self.workers[msg['worker_name']] = worker if msg['message_type'] == 'remove_worker': if not msg['worker_name'] in self.workers: log.error('Cannot remove worker, name unknown: %s' % (msg['worker_name'])) return yield self.workers[msg['worker_name']].stopService() self.workers[msg['worker_name']].disownServiceParent() self.workers.pop(msg['worker_name']) except Exception as ex: log.error("Control received: %s" % (msg)) log.error("Unexpected error %s" % repr(ex))
def handle_event(self, event): message = yield self.find_message_for_event(event) if message is None: log.error('Unable to find message for %s, user_message_id: %s' % (event['event_type'], event.get('user_message_id'))) return msg_mdh = self.get_metadata_helper(message) conv = yield msg_mdh.get_conversation() if conv: window_id = self.get_window_id(conv.key, conv.batch.key) flight_key = yield self.window_manager.get_internal_id( window_id, message['message_id']) yield self.window_manager.remove_key(window_id, flight_key)
def dispatch_inbound_message(self, msg): keyword = get_first_word(msg['content']).lower() matched = False for rule in self.rules: if self.is_msg_matching_routing_rules(keyword, msg, rule): matched = True # copy message so that the middleware doesn't see a particular # message instance multiple times self.publish_exposed_inbound(rule['app'], msg.copy()) if not matched: if self.fallback_application is not None: self.publish_exposed_inbound(self.fallback_application, msg) else: log.error(DispatcherError( 'Message could not be routed: %r' % (msg,)))
def dispatch_inbound_event(self, msg): yield self._redis_d # Horrible hack to ensure we have it setup. message_key = self.get_message_key(msg['user_message_id']) session = yield self.session_manager.load_session(message_key) name = session.get('name') if not name: log.error( DispatcherError( "No transport_name for return route found in Redis" " while dispatching transport event for message %s" % (msg['user_message_id'], ))) try: self.publish_exposed_event(name, msg) except: log.error(DispatcherError("No publishing route for %s" % (name, )))
def receive_control_message(self, msg): try: log.debug('Received control message %s' % (msg, )) if msg['action'] == 'add_exposed': self.setup_exposed(msg['exposed_name']) self.append_mapping(msg['exposed_name'], msg['rules']) return if msg['action'] == 'remove_exposed': self.clear_mapping(msg['exposed_name']) self.remove_exposed(msg['exposed_name']) return except: exc_type, exc_value, exc_traceback = sys.exc_info() log.error( "Error during consume control message: %r" % traceback.format_exception(exc_type, exc_value, exc_traceback))
def get_next(self, since_dt): try: recurring_type = self.schedule_definition['recurring'] if recurring_type == 'daily': return self.get_next_daily(since_dt) elif recurring_type == 'day_of_month': return self.get_next_day_of_month(since_dt) elif recurring_type == 'day_of_week': return self.get_next_day_of_week(since_dt) elif recurring_type == 'never': return None else: raise ValueError("Invalid value for 'recurring': %r" % (recurring_type, )) except Exception: log.error(None, "Error processing schedule.")
def receive_control_message(self, msg): try: log.debug('Received control message %s' % (msg,)) if msg['action'] == 'add_exposed': self.setup_exposed(msg['exposed_name']) self.append_mapping(msg['exposed_name'], msg['rules']) return if msg['action'] == 'remove_exposed': self.clear_mapping(msg['exposed_name']) self.remove_exposed(msg['exposed_name']) return except: exc_type, exc_value, exc_traceback = sys.exc_info() log.error( "Error during consume control message: %r" % traceback.format_exception(exc_type, exc_value, exc_traceback))
def dispatch_request(self, command): resource_name, sep, rest = command["cmd"].partition(".") if not sep: resource_name, rest = "", resource_name command["cmd"] = rest resource = self.resources.resources.get(resource_name, self.fallback_resource) try: reply = yield resource.dispatch_request(self, command) except Exception, e: # errors here are bugs in Vumi so we always log them # via Twisted. However, we reply to the sandbox with # a failure and log via the sandbox api so that the # sandbox owner can be notified. log.error() self.log(str(e), level=logging.ERROR) reply = SandboxCommand(reply=True, cmd_id=command["cmd_id"], success=False, reason=unicode(e))
def dispatch_inbound_message(self, msg): keyword = get_first_word(msg['content']).lower() matched = False for rule in self.rules: if self.is_msg_matching_routing_rules(keyword, msg, rule): matched = True # copy message so that the middleware doesn't see a particular # message instance multiple times self.publish_exposed_inbound(rule['app'], msg.copy()) if not matched: if self.fallback_application is not None: self.publish_exposed_inbound(self.fallback_application, msg) else: log.error( DispatcherError('Message could not be routed: %r' % (msg, )))
def get_next(self, since_dt): try: recurring_type = self.schedule_definition['recurring'] if recurring_type == 'daily': return self.get_next_daily(since_dt) elif recurring_type == 'day_of_month': return self.get_next_day_of_month(since_dt) elif recurring_type == 'day_of_week': return self.get_next_day_of_week(since_dt) elif recurring_type == 'never': return None else: raise ValueError( "Invalid value for 'recurring': %r" % (recurring_type,)) except Exception: log.error(None, "Error processing schedule.")
def release_tag(self, tag): """Release a tag back to the pool it came from. Tags should be released only once a conversation is finished. :type pool: str :param pool: name of the pool to return the tag too (must be the same as the name of the pool the tag came from). :rtype: None. """ user_account = yield self.get_user_account() try: user_account.tags.remove(list(tag)) except ValueError, e: log.error("Tag not allocated to account: %s" % (tag, ), e)
def release_tag(self, tag): """Release a tag back to the pool it came from. Tags should be released only once a conversation is finished. :type pool: str :param pool: name of the pool to return the tag too (must be the same as the name of the pool the tag came from). :rtype: None. """ user_account = yield self.get_user_account() try: user_account.tags.remove(list(tag)) except ValueError, e: log.error("Tag not allocated to account: %s" % (tag,), e)
def handle_bad_request_fields(self, message_id, request, errors): req = self.get_request_dict(request) log.error( "Bad request fields for inbound message: %s %s" % (errors, req,)) self.respond(message_id, http.BAD_REQUEST, errors) yield self.add_status( component='inbound', status='down', type='request_bad_fields', message='Bad request fields', details={ 'request': req, 'errors': errors })
def handle_raw_inbound_message(self, message_id, request): op_code = request.args.get('opCode')[0] to_addr = None if op_code == "BEG": to_addr = request.args.get('INPUT')[0] content = None yield self.set_ussd_for_msisdn_session( request.args.get('MSISDN')[0], request.args.get('sessionID')[0], to_addr) else: to_addr = yield self.get_ussd_for_msisdn_session( request.args.get('MSISDN')[0], request.args.get('sessionID')[0]) content = request.args.get('INPUT')[0] if ((request.args.get('ABORT')[0] not in ('0', 'null')) or (op_code == 'ABO')): # respond to phones aborting a session self.finish_request(message_id, '') event = TransportUserMessage.SESSION_CLOSE else: event = self.EVENT_MAP.get(op_code, TransportUserMessage.SESSION_RESUME) if to_addr is None: # we can't continue so finish request and log error self.finish_request(message_id, '') log.error(CellulantError( "Failed redis USSD to_addr lookup for %s" % request.args)) else: transport_metadata = { 'session_id': request.args.get('sessionID')[0], } self.publish_message( message_id=message_id, content=content, to_addr=to_addr, from_addr=request.args.get('MSISDN')[0], session_event=event, transport_name=self.transport_name, transport_type=self.transport_type, transport_metadata=transport_metadata, )
def handle_raw_inbound_message(self, message_id, request): op_code = request.args.get('opCode')[0] to_addr = None if op_code == "BEG": to_addr = request.args.get('INPUT')[0] content = None yield self.set_ussd_for_msisdn_session( request.args.get('MSISDN')[0], request.args.get('sessionID')[0], to_addr) else: to_addr = yield self.get_ussd_for_msisdn_session( request.args.get('MSISDN')[0], request.args.get('sessionID')[0]) content = request.args.get('INPUT')[0] if ((request.args.get('ABORT')[0] not in ('0', 'null')) or (op_code == 'ABO')): # respond to phones aborting a session self.finish_request(message_id, '') event = TransportUserMessage.SESSION_CLOSE else: event = self.EVENT_MAP.get(op_code, TransportUserMessage.SESSION_RESUME) if to_addr is None: # we can't continue so finish request and log error self.finish_request(message_id, '') log.error( CellulantError("Failed redis USSD to_addr lookup for %s" % request.args)) else: transport_metadata = { 'session_id': request.args.get('sessionID')[0], } self.publish_message( message_id=message_id, content=content, to_addr=to_addr, from_addr=request.args.get('MSISDN')[0], session_event=event, transport_name=self.transport_name, transport_type=self.transport_type, transport_metadata=transport_metadata, )
def dispatch_request(self, command): resource_name, sep, rest = command['cmd'].partition('.') if not sep: resource_name, rest = '', resource_name command['cmd'] = rest resource = self.resources.resources.get(resource_name, self.fallback_resource) try: reply = yield resource.dispatch_request(self, command) except Exception, e: # errors here are bugs in Vumi so we always log them # via Twisted. However, we reply to the sandbox with # a failure and log via the sandbox api so that the # sandbox owner can be notified. log.error() self.log(str(e), level=logging.ERROR) reply = SandboxCommand(reply=True, cmd_id=command['cmd_id'], success=False, reason=unicode(e))
def log(self, msg, level='msg'): timezone = None local_time = self.get_local_time() rkey = "%slogs" % (self.r_prefix,) self.r_server.zremrangebyscore( rkey, 1, get_local_time_as_timestamp( local_time - timedelta(hours=2)) ) self.r_server.zadd( rkey, "[%s] %s" % ( time_to_vusion_format(local_time), msg), get_local_time_as_timestamp(local_time)) if (level == 'msg'): log.msg('[%s] %s' % (self.control_name, msg)) else: log.error('[%s] %s' % (self.control_name, msg))
def reconcile_cache(self, user_api, conversation_key, delta=0.01): """Reconcile the cached values for the conversation. Checks whether caches for a conversation are off by a given delta and if so, initiates a full cache reconciliation. :param VumiUserApi user_api: The Api for this user :param str conversation_key: The key of the conversation to reconcile :param float delta: If the key count difference between the message_store and the cache is bigger than the delta a reconciliation is initiated. """ conv = yield user_api.get_wrapped_conversation(conversation_key) if conv is None: log.error('Conversation does not exist: %s' % (conversation_key, )) return log.msg('Reconciling cache for %s' % (conversation_key, )) message_store = user_api.api.mdb if (yield message_store.needs_reconciliation(conv.batch.key, delta)): yield message_store.reconcile_cache(conv.batch.key) log.msg('Cache reconciled for %s' % (conversation_key, ))
def reconcile_cache(self, user_api, conversation_key, delta=0.01): """Reconcile the cached values for the conversation. Checks whether caches for a conversation are off by a given delta and if so, initiates a full cache reconciliation. :param VumiUserApi user_api: The Api for this user :param str conversation_key: The key of the conversation to reconcile :param float delta: If the key count difference between the message_store and the cache is bigger than the delta a reconciliation is initiated. """ conv = yield user_api.get_wrapped_conversation(conversation_key) if conv is None: log.error('Conversation does not exist: %s' % (conversation_key,)) return log.msg('Reconciling cache for %s' % (conversation_key,)) message_store = user_api.api.mdb if (yield message_store.needs_reconciliation(conv.batch.key, delta)): yield message_store.reconcile_cache(conv.batch.key) log.msg('Cache reconciled for %s' % (conversation_key,))
def teardown_stream(self, err): if not (err is None or err.trap(ConnectionDone)): log.error(err) log.info('Unregistering: %s, %s' % (self._rk, err.getErrorMessage())) return self.worker.unregister_client(self._rk, self._callback)
def set_destination(self, msg, target, direction, push_hops=True): """Parse a target `(str(go_connector), endpoint)` pair and determine the corresponding dispatcher connector to publish on. Set any appropriate Go helper_metadata required by the destination. Raises `UnroutableMessageError` if the parsed `GoConnector` has a connector type not approriate to the message direction. Note: `str(go_connector)` is what is stored in Go routing tables. """ msg_mdh = self.get_metadata_helper(msg) conn = GoConnector.parse(target[0]) if direction == self.INBOUND: allowed_types = (self.CONVERSATION, self.ROUTER, self.OPT_OUT, self.BILLING) else: allowed_types = (self.ROUTER, self.TRANSPORT_TAG, self.BILLING) if conn.ctype not in allowed_types: raise UnroutableMessageError( "Destination connector of invalid type: %s" % conn, msg) if conn.ctype == conn.CONVERSATION: msg_mdh.set_conversation_info(conn.conv_type, conn.conv_key) dst_connector_name = self.get_application_connector(conn.conv_type) elif conn.ctype == conn.ROUTER: msg_mdh.set_router_info(conn.router_type, conn.router_key) dst_connector_name = self.get_router_connector( conn.router_type, self.router_direction(direction)) elif conn.ctype == conn.TRANSPORT_TAG: msg_mdh.set_tag([conn.tagpool, conn.tagname]) tagpool_metadata = yield msg_mdh.get_tagpool_metadata() transport_name = tagpool_metadata.get('transport_name') if transport_name is None: raise UnroutableMessageError( "No transport name found for tagpool %r" % conn.tagpool, msg) if self.connector_type(transport_name) != self.TRANSPORT_TAG: raise UnroutableMessageError( "Transport name %r found in tagpool metadata for pool" " %r is invalid." % (transport_name, conn.tagpool), msg) dst_connector_name = transport_name msg['transport_name'] = transport_name transport_type = tagpool_metadata.get('transport_type') if transport_type is not None: msg['transport_type'] = transport_type else: log.error( "No transport type found for tagpool %r while routing %s" % (conn.tagpool, msg)) elif conn.ctype == conn.OPT_OUT: dst_connector_name = self.opt_out_connector elif conn.ctype == conn.BILLING: if direction == self.INBOUND: dst_connector_name = self.billing_inbound_connector else: dst_connector_name = self.billing_outbound_connector else: raise UnroutableMessageError( "Serious error. Reached apparently unreachable state" " in which destination connector type is valid but" " unknown. Bad connector is: %s" % conn, msg) if push_hops: rmeta = RoutingMetadata(msg) rmeta.push_destination(str(conn), target[1]) returnValue((dst_connector_name, target[1]))
def default_errback(self, f, msg, connector_name): log.error(f, "Error routing message for %s" % (connector_name, ))
def process_unknown_cmd(self, method_name, *args, **kwargs): log.error("Unknown vumi API command: %s(%s, %s)" % (method_name, args, kwargs))
def _publish_message(self, message, endpoint_name=None): if not self.get_metadata_helper(message).get_conversation_info: log.error("Conversation metadata missing for message for %s: %s" % (type(self).__name__, message)) return super(GoApplicationWorker, self)._publish_message(message, endpoint_name)
def process_unknown_cmd(self, method_name, *args, **kwargs): log.error("Unknown vumi API command: %s(%s, %s)" % ( method_name, args, kwargs))