Skip to content

Commit

Permalink
Merge branch 'develop' into feature/issue-974-fake-connections-for-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jerith committed Oct 23, 2015
2 parents 8635207 + c61d81a commit b3512b9
Show file tree
Hide file tree
Showing 31 changed files with 1,331 additions and 212 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -26,4 +26,4 @@ dropin.cache
/django_test_results.xml
/pep8.txt
/.tox
/.cache
/.cache/
2 changes: 0 additions & 2 deletions config/example_http_relay.yaml

This file was deleted.

13 changes: 0 additions & 13 deletions config/smpp_test_dispatcher.yaml

This file was deleted.

2 changes: 1 addition & 1 deletion docs/conf.py
Expand Up @@ -53,7 +53,7 @@
# The short X.Y version.
version = '0.5'
# The full version, including alpha/beta/rc tags.
release = '0.5.30a0'
release = '0.5.33a'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
126 changes: 126 additions & 0 deletions docs/transports/smpp.rst
Expand Up @@ -112,3 +112,129 @@ message_id in the response.
Followup pdu's from the SMSC (i.e. delivery reports) will reference
the original message by the message_id held by the SMSC which was
returned in the submit_sm_resp.

.. _smpp-status-events:

Status event catalogue
^^^^^^^^^^^^^^^^^^^^^^

The SMPP transport publishes the following status events when status event
publishing is enabled.

``starting``
~~~~~~~~~~~~

Published when the transport is busy starting.

Fields:

* ``status``: ``down``
* ``type``: ``starting``
* ``component``: ``smpp``


``binding``
~~~~~~~~~~~

Published when the transport has established a connection to the SMSC, has
attempted to bind, and is waiting for the SMSC's response.

Fields:

* ``status``: ``down``
* ``type``: ``binding``
* ``component``: ``smpp``


``bound``
~~~~~~~~~

Published when the transport has received a bind response from the SMSC and is
ready to send and receive messages.

Fields:

- ``status``: ``ok``
- ``type``: ``bound``
- ``component``: ``smpp``


``bind_timeout``
~~~~~~~~~~~~~~~~

Published when the transport has not bound within the interval given by the
``smpp_bind_timeout`` config field.

Fields:

- ``status``: ``down``
- ``type``: ``bind_timeout``
- ``component``: ``smpp``


``unbinding``
~~~~~~~~~~~~~

Published when the transport has attempted to unbind, and is waiting for the
SMSC's response.

Fields:

- ``status``: ``down``
- ``type``: ``unbinding``
- ``component``: ``smpp``


``connection_lost``
~~~~~~~~~~~~~~~~~~

Published when a transport loses its connection to the SMSC. This occurs in the
following situations:

- after successfully unbinding
- if an unbind attempt times out
- when the connection to the SMSC is lost unexpectedly

Fields:

- ``status``: ``down``
- ``type``: ``connection_lost``
- ``component``: ``smpp``


``throttled``
~~~~~~~~~~~~~

Published when throttling starts for the transport and when throttling
continues for a transport after rebinding. Throttling starts in two situations:

- the SMSC has replied to a message we attempted to send with an
``ESME_RTHROTTLED`` response
- we have reached the maximum number of transmissions per second allowed by the
transport (set by the ``mt_tps`` config field), where a transmission is a
mobile-terminating message put onto the wire by the transport.

Fields:

- ``status``: ``degraded``
- ``type``: ``throttled``
- ``component``: ``smpp``


``throttled_end``
~~~~~~~~~~~~~~~~~

Published when the transport is no longer throttled. This happens in two
situations:

- we have retried an earlier message we attempted to send that was given a
``ESME_RTHROTTLED`` response, and the SMSC has responded to the retried
message with a ``ESME_ROK`` response (that is, the retry was successful)
- the transport is no longer at the maximum number of transmissions per
second

Fields:

- ``status``: ``ok``
- ``type``: ``throttled_end``
- ``component``: ``smpp``
36 changes: 0 additions & 36 deletions etc/supervisord.smpp_test.conf
Expand Up @@ -21,24 +21,6 @@ supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
serverurl=http://127.0.0.1:7010 ; use an http:// url to specify an inet socket


[program:smpp_test_smsc_transport]
numprocs=1
numprocs_start=1
process_name=%(program_name)s_%(process_num)s
command=twistd -n
--pidfile=./tmp/pids/%(program_name)s_%(process_num)s.pid
vumi_worker
--worker_class=vumi.transports.smpp.service.SmppService
--vhost=/develop
--config=./config/smpp_test.yaml
stdout_logfile=./logs/%(program_name)s_%(process_num)s.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10
stderr_logfile=./logs/%(program_name)s_%(process_num)s.err
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=10
autorestart=true

[program:smpp_test_esme_transport]
numprocs=1
numprocs_start=0
Expand All @@ -57,24 +39,6 @@ stderr_logfile_maxbytes=10MB
stderr_logfile_backups=10
autorestart=true

[program:smpp_test_dispatcher]
numprocs=1
numprocs_start=1
process_name=%(program_name)s_%(process_num)s
command=twistd -n
--pidfile=./tmp/pids/%(program_name)s_%(process_num)s.pid
vumi_worker
--worker_class=vumi.dispatchers.simple.dispatcher.SimpleDispatcher
--vhost=/develop
--config=./config/smpp_test_dispatcher.yaml
stdout_logfile=./logs/%(program_name)s_%(process_num)s.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10
stderr_logfile=./logs/%(program_name)s_%(process_num)s.err
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=10
autorestart=true

[program:smpp_test_http_poster]
numprocs=1
numprocs_start=1
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -12,7 +12,7 @@

setup(
name="vumi",
version="0.5.30a0",
version="0.5.33a",
url='http://github.com/praekelt/vumi',
license='BSD',
description="Super-scalable messaging engine for the delivery of SMS, "
Expand Down
2 changes: 1 addition & 1 deletion vumi/__init__.py
Expand Up @@ -2,4 +2,4 @@
Vumi scalable text messaging engine.
"""

__version__ = "0.5.30a0"
__version__ = "0.5.33a"
25 changes: 24 additions & 1 deletion vumi/connectors.py
@@ -1,8 +1,9 @@
from twisted.internet.defer import gatherResults, inlineCallbacks, returnValue

from vumi import log
from vumi.message import TransportMessage, TransportEvent, TransportUserMessage
from vumi.middleware import MiddlewareStack
from vumi.message import (
TransportMessage, TransportEvent, TransportUserMessage, TransportStatus)


class IgnoreMessage(Exception):
Expand Down Expand Up @@ -162,3 +163,25 @@ def _ignore_message(self, failure, msg):
return self.publish_event(TransportEvent(
user_message_id=msg['message_id'], nack_reason=str(failure.value),
event_type='nack'))


class PublishStatusConnector(BaseConnector):
@inlineCallbacks
def setup(self):
yield self._setup_publisher('status')

def publish_status(self, msg):
return self._publish_message('status', msg, endpoint_name=None)


class ReceiveStatusConnector(BaseConnector):
@inlineCallbacks
def setup(self):
yield self._setup_consumer(
'status', TransportStatus, self.default_status_handler)

def default_status_handler(self, msg):
log.warning("No status handler for %r: %r" % (self.name, msg))

def set_status_handler(self, handler):
self._set_default_endpoint_handler('status', handler)
Empty file.
37 changes: 0 additions & 37 deletions vumi/dispatchers/simple/dispatcher.py

This file was deleted.

Empty file.
46 changes: 0 additions & 46 deletions vumi/dispatchers/simple/tests/test_dispatcher.py

This file was deleted.

24 changes: 24 additions & 0 deletions vumi/message.py
Expand Up @@ -429,3 +429,27 @@ def validate_fields(self):
self.assert_field_present(extra_field)
if not check(self[extra_field]):
raise InvalidMessageField(extra_field)


class TransportStatus(TransportMessage):
"""Message about a status event emitted by a transport.
"""
MESSAGE_TYPE = 'status_event'
STATUSES = frozenset(('ok', 'degraded', 'down'))

def process_fields(self, fields):
super(TransportStatus, self).process_fields(fields)
fields.setdefault('reasons', [])
fields.setdefault('details', {})
return fields

def validate_fields(self):
super(TransportStatus, self).validate_fields()
self.assert_field_present('component')
self.assert_field_present('status')
self.assert_field_present('type')
self.assert_field_present('message')

if self.payload['status'] not in self.STATUSES:
raise InvalidMessageField(
"Unknown status %r" % (self.payload['status'],))

0 comments on commit b3512b9

Please sign in to comment.