Skip to content
This repository has been archived by the owner on Jun 12, 2018. It is now read-only.

Commit

Permalink
Send session lengths from billing dispatcher to billing api
Browse files Browse the repository at this point in the history
  • Loading branch information
justinvdm committed Feb 13, 2015
1 parent 4b2267e commit e00159b
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 6 deletions.
41 changes: 38 additions & 3 deletions go/vumitools/billing_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def _call_api(self, path, query=None, data=None, method='GET'):

def create_transaction(self, account_number, message_id, tag_pool_name,
tag_name, provider, message_direction,
session_created, transaction_type):
session_created, transaction_type, session_length):
"""Create a new transaction for the given ``account_number``"""
data = {
'account_number': account_number,
Expand All @@ -75,6 +75,7 @@ def create_transaction(self, account_number, message_id, tag_pool_name,
'message_direction': message_direction,
'session_created': session_created,
'transaction_type': transaction_type,
'session_length': session_length,
}
return self._call_api("/transactions", data=data, method='POST')

Expand All @@ -90,6 +91,10 @@ class BillingDispatcherConfig(Dispatcher.CONFIG_CLASS, GoWorkerConfigMixin):
disable_billing = ConfigBool(
"Disable calling the billing API and just pass through all messages.",
static=True, default=False)
session_metadata_field = ConfigText(
"Name of the session metadata field to look for in each message to "
"calculate session length",
static=True, default='session_metadata')

def post_validate(self):
if len(self.receive_inbound_connectors) != 1:
Expand Down Expand Up @@ -127,6 +132,7 @@ def setup_dispatcher(self):
self.api_url = config.api_url
self.billing_api = BillingApi(self.api_url, config.retry_delay)
self.disable_billing = config.disable_billing
self.session_metadata_field = config.session_metadata_field

@inlineCallbacks
def teardown_dispatcher(self):
Expand All @@ -144,6 +150,33 @@ def validate_metadata(self, msg):
raise BillingError(
"No tag found for message %s" % (msg.get('message_id'),))

@classmethod
def determine_session_length(cls, session_metadata_field, msg):
"""
Determines the length of the session from metadata attached to the
message. The billing dispatcher looks for the following on the message
payload to calculate this:
- ``helper_metadata.<session_metadata_field>.session_start``
- ``helper_metadata.<session_metadata_field>.session_end``
If either of these fields are not present, the message is assumed to not
contain enough information to calculate the session length and ``None``
is returned
"""
metadata = msg['helper_metadata'].get(session_metadata_field, {})

if 'session_start' not in metadata:
return None

if 'session_end' not in metadata:
return None

return metadata['session_end'] - metadata['session_start']

def _determine_session_length(self, msg):
return self.determine_session_length(self.session_metadata_field, msg)

@inlineCallbacks
def create_transaction_for_inbound(self, msg):
"""Create a transaction for the given inbound message"""
Expand All @@ -157,7 +190,8 @@ def create_transaction_for_inbound(self, msg):
provider=msg.get('provider'),
message_direction=self.MESSAGE_DIRECTION_INBOUND,
session_created=session_created,
transaction_type=self.TRANSACTION_TYPE_MESSAGE)
transaction_type=self.TRANSACTION_TYPE_MESSAGE,
session_length=self._determine_session_length(msg))

@inlineCallbacks
def create_transaction_for_outbound(self, msg):
Expand All @@ -172,7 +206,8 @@ def create_transaction_for_outbound(self, msg):
provider=msg.get('provider'),
message_direction=self.MESSAGE_DIRECTION_OUTBOUND,
session_created=session_created,
transaction_type=self.TRANSACTION_TYPE_MESSAGE)
transaction_type=self.TRANSACTION_TYPE_MESSAGE,
session_length=self._determine_session_length(msg))

@inlineCallbacks
def process_inbound(self, config, msg, connector_name):
Expand Down
181 changes: 178 additions & 3 deletions go/vumitools/tests/test_billing_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def _record(self, items, vars):

def create_transaction(self, account_number, message_id, tag_pool_name,
tag_name, provider, message_direction,
session_created, transaction_type):
session_created, transaction_type, session_length):
self._record(self.transactions, locals())
return {
"id": 1,
Expand All @@ -48,7 +48,8 @@ def create_transaction(self, account_number, message_id, tag_pool_name,
"created": "2013-10-30T10:42:51.144745+02:00",
"last_modified": "2013-10-30T10:42:51.144745+02:00",
"status": "Completed",
"transaction_type": transaction_type
"transaction_type": transaction_type,
"session_length": session_length
}


Expand Down Expand Up @@ -110,6 +111,7 @@ def test_create_transaction_request(self):
'message_direction': "Inbound",
'session_created': False,
'transaction_type': BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
'session_length': 23,
}
yield self.billing_api.create_transaction(**kwargs)
self.assertEqual(hrm.request.uri, "%stransactions" % (self.api_url,))
Expand All @@ -135,6 +137,7 @@ def test_create_transaction_response(self):
"last_modified": "2013-10-30T10:42:51.144745+02:00",
"status": "Completed",
"transaction_type": BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
'session_length': 23,
}
response = self._mk_response(
delivered_body=json.dumps(delivered_body, cls=JSONEncoder))
Expand All @@ -152,6 +155,7 @@ def test_create_transaction_response(self):
'message_direction': "Inbound",
'session_created': False,
"transaction_type": BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
'session_length': 23,
}
result = yield self.billing_api.create_transaction(**kwargs)
self.assertEqual(result, delivered_body)
Expand All @@ -174,6 +178,7 @@ def test_create_transaction_http_error(self):
'message_direction': "Inbound",
'session_created': False,
'transaction_type': BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
'session_length': 23,
}
d = self.billing_api.create_transaction(**kwargs)
yield self.assertFailure(d, BillingError)
Expand All @@ -197,6 +202,7 @@ def test_create_transaction_network_error(self):
"last_modified": "2013-10-30T10:42:51.144745+02:00",
"status": "Completed",
"transaction_type": BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
'session_length': 23,
}
response = self._mk_response(
delivered_body=json.dumps(delivered_body, cls=JSONEncoder))
Expand All @@ -214,6 +220,7 @@ def test_create_transaction_network_error(self):
'message_direction': "Inbound",
'session_created': False,
"transaction_type": BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
'session_length': 23,
}
result = yield self.billing_api.create_transaction(**kwargs)
self.assertEqual(result, delivered_body)
Expand All @@ -236,6 +243,7 @@ def test_create_transaction_network_error_on_retry(self):
'message_direction': "Inbound",
'session_created': False,
"transaction_type": BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
'session_length': 23,
}
d = self.billing_api.create_transaction(**kwargs)
yield self.assertFailure(d, MockNetworkError)
Expand Down Expand Up @@ -291,12 +299,14 @@ def make_dispatch_outbound(self, content, user_account=None, tag=None,
self.add_md(msg, user_account=user_account, tag=tag, is_paid=is_paid)
return self.ro_helper.dispatch_outbound(msg).addCallback(lambda _: msg)

def assert_transaction(self, msg, direction, session_created):
def assert_transaction(self, msg, direction, session_created,
session_metadata_field='session_metadata'):
md = MessageMetadataHelper(self.vumi_helper.get_vumi_api(), msg)
direction = {
"inbound": BillingDispatcher.MESSAGE_DIRECTION_INBOUND,
"outbound": BillingDispatcher.MESSAGE_DIRECTION_OUTBOUND,
}[direction]

self.assertEqual(self.billing_api.transactions, [{
"account_number": md.get_account_key(),
"message_id": msg["message_id"],
Expand All @@ -306,11 +316,40 @@ def assert_transaction(self, msg, direction, session_created):
"message_direction": direction,
"session_created": session_created,
"transaction_type": BillingDispatcher.TRANSACTION_TYPE_MESSAGE,
"session_length": BillingDispatcher.determine_session_length(
session_metadata_field, msg),
}])

def assert_no_transactions(self):
self.assertEqual(self.billing_api.transactions, [])

def test_determine_session_length(self):
msg = self.msg_helper.make_inbound('roar', helper_metadata={
'foo': {
'session_start': 32,
'session_end': 55,
}
})

self.assertEqual(
BillingDispatcher.determine_session_length('foo', msg), 23)

def test_determine_session_length_no_start(self):
msg = self.msg_helper.make_inbound('roar', helper_metadata={
'foo': {'session_start': 32}
})

self.assertEqual(
BillingDispatcher.determine_session_length('foo', msg), None)

def test_determine_session_length_no_end(self):
msg = self.msg_helper.make_inbound('roar', helper_metadata={
'foo': {'session_end': 55}
})

self.assertEqual(
BillingDispatcher.determine_session_length('foo', msg), None)

@inlineCallbacks
def test_inbound_message(self):
yield self.get_dispatcher()
Expand Down Expand Up @@ -388,6 +427,74 @@ def test_inbound_message_provider(self):
self.assertEqual([msg], self.ro_helper.get_dispatched_inbound())
self.assert_transaction(msg, "inbound", session_created=False)

@inlineCallbacks
def test_inbound_message_session_length(self):
yield self.get_dispatcher()
msg = yield self.make_dispatch_inbound(
"inbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={
'session_metadata': {
'session_start': 32,
'session_end': 55,
}
})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ro_helper.get_dispatched_inbound())
self.assert_transaction(msg, "inbound", session_created=False)

@inlineCallbacks
def test_inbound_message_session_length_no_start(self):
yield self.get_dispatcher()
msg = yield self.make_dispatch_inbound(
"inbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={'session_metadata': {'session_end': 55}})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ro_helper.get_dispatched_inbound())
self.assert_transaction(msg, "inbound", session_created=False)

@inlineCallbacks
def test_inbound_message_session_length_no_end(self):
yield self.get_dispatcher()
msg = yield self.make_dispatch_inbound(
"inbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={'session_metadata': {'session_start': 32}})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ro_helper.get_dispatched_inbound())
self.assert_transaction(msg, "inbound", session_created=False)

@inlineCallbacks
def test_inbound_message_session_length_custom_field(self):
yield self.get_dispatcher(session_metadata_field='foo')

msg = yield self.make_dispatch_inbound(
"inbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={
'foo': {
'session_start': 32,
'session_end': 55,
}
})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ro_helper.get_dispatched_inbound())

self.assert_transaction(
msg,
"inbound",
session_created=False,
session_metadata_field='foo')

@inlineCallbacks
def test_outbound_message(self):
yield self.get_dispatcher()
Expand Down Expand Up @@ -564,3 +671,71 @@ def create_transaction(*args, **kw):
self.assertEqual(
[err.getErrorMessage() for err in errors],
["I can't do that, Dave."])

@inlineCallbacks
def test_outbound_message_session_length(self):
yield self.get_dispatcher()
msg = yield self.make_dispatch_outbound(
"outbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={
'session_metadata': {
'session_start': 32,
'session_end': 55,
}
})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ri_helper.get_dispatched_outbound())
self.assert_transaction(msg, "outbound", session_created=False)

@inlineCallbacks
def test_outbound_message_session_length_no_start(self):
yield self.get_dispatcher()
msg = yield self.make_dispatch_outbound(
"outbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={'session_metadata': {'session_end': 55}})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ri_helper.get_dispatched_outbound())
self.assert_transaction(msg, "outbound", session_created=False)

@inlineCallbacks
def test_outbound_message_session_length_no_end(self):
yield self.get_dispatcher()
msg = yield self.make_dispatch_outbound(
"outbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={'session_metadata': {'session_start': 32}})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ri_helper.get_dispatched_outbound())
self.assert_transaction(msg, "outbound", session_created=False)

@inlineCallbacks
def test_outbound_message_session_length_custom_field(self):
yield self.get_dispatcher(session_metadata_field='foo')

msg = yield self.make_dispatch_outbound(
"outbound",
user_account="12345",
tag=("pool1", "1234"),
helper_metadata={
'foo': {
'session_start': 32,
'session_end': 55,
}
})

self.add_md(msg, is_paid=True)
self.assertEqual([msg], self.ri_helper.get_dispatched_outbound())

self.assert_transaction(
msg,
"outbound",
session_created=False,
session_metadata_field='foo')

0 comments on commit e00159b

Please sign in to comment.