Пример #1
0
 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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
 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)
Пример #5
0
    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)
Пример #6
0
 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, ))
Пример #7
0
 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,))
Пример #8
0
 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,)))
Пример #9
0
 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)))
Пример #10
0
 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, )))
Пример #11
0
 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)
Пример #12
0
 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)))
Пример #13
0
 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'], ))
Пример #14
0
 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'],))
Пример #15
0
 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, ))
Пример #16
0
 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,))
Пример #17
0
    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)
Пример #18
0
    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})
Пример #19
0
    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)
Пример #20
0
 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'],)))
Пример #21
0
    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)
Пример #22
0
 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
Пример #23
0
 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'], )))
Пример #24
0
    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)
Пример #25
0
 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
Пример #26
0
 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, ))
Пример #27
0
 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,))
Пример #28
0
 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,)))
Пример #29
0
 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))
Пример #30
0
    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)
Пример #31
0
    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))
Пример #32
0
    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))
Пример #33
0
    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)
Пример #34
0
 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,)))
Пример #35
0
 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, )))
Пример #36
0
 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))
Пример #37
0
 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.")
Пример #38
0
 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))
Пример #39
0
 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))
Пример #40
0
 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, )))
Пример #41
0
 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.")
Пример #42
0
    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)
Пример #43
0
    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)
Пример #44
0
    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
            })
Пример #45
0
    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,
            )
Пример #46
0
    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,
            )
Пример #47
0
 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))
Пример #48
0
 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))
Пример #49
0
    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, ))
Пример #50
0
    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,))
Пример #51
0
 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)
Пример #52
0
    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]))
Пример #53
0
 def default_errback(self, f, msg, connector_name):
     log.error(f, "Error routing message for %s" % (connector_name, ))
Пример #54
0
 def process_unknown_cmd(self, method_name, *args, **kwargs):
     log.error("Unknown vumi API command: %s(%s, %s)" %
               (method_name, args, kwargs))
Пример #55
0
 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)
Пример #56
0
 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)
Пример #57
0
 def process_unknown_cmd(self, method_name, *args, **kwargs):
     log.error("Unknown vumi API command: %s(%s, %s)" % (
         method_name, args, kwargs))