Fix race condition in V1 Records API

When listing records in the V1 API, two calls to central
are made - once for records once for recordsets - if the
content of either changes between the two calls, a failure
can occour. Instead, we already have all the data we need
so use it from the recordsets rather than make two calls

Change-Id: Ic43d7e8c0d60267ec4788b63ed5f7e88e7bbe625
Closes-Bug: 1487934
This commit is contained in:
Kiall Mac Innes 2015-09-22 14:05:01 +01:00
parent 3e3d4681b7
commit eea5c1e8ad
2 changed files with 5 additions and 17 deletions

View File

@ -92,15 +92,6 @@ def _format_record_v1(record, recordset):
return record
def _fetch_domain_recordsets(context, domain_id):
criterion = {'domain_id': domain_id}
central_api = central_rpcapi.CentralAPI.get_instance()
recordsets = central_api.find_recordsets(context, criterion)
return dict((r['id'], r) for r in recordsets)
@blueprint.route('/schemas/record', methods=['GET'])
def get_record_schema():
return flask.jsonify(record_schema.raw)
@ -154,15 +145,12 @@ def get_records(domain_id):
# return an empty records array instead of a domain not found
central_api.get_domain(context, domain_id)
records = central_api.find_records(context, {'domain_id': domain_id})
recordsets = central_api.find_recordsets(context, {'domain_id': domain_id})
recordsets = _fetch_domain_recordsets(context, domain_id)
records = []
def _inner(record):
recordset = recordsets[record['recordset_id']]
return _format_record_v1(record, recordset)
records = [_inner(r) for r in records]
for rrset in recordsets:
records.extend([_format_record_v1(r, rrset) for r in rrset.records])
return flask.jsonify(records_schema.filter({'records': records}))

View File

@ -466,7 +466,7 @@ class ApiV1RecordsTest(ApiV1Test):
self.assertIn('records', response.json)
self.assertEqual(4, len(response.json['records']))
@patch.object(central_service.Service, 'find_records',
@patch.object(central_service.Service, 'get_domain',
side_effect=messaging.MessagingTimeout())
def test_get_records_timeout(self, _):
self.get('domains/%s/records' % self.domain['id'],