Skip to content

Commit

Permalink
3245 datastore_active race condition
Browse files Browse the repository at this point in the history
`datastore_create` directly updates database and solr index and
this reduces possibility of conflicts inside simultaneous calls
  • Loading branch information
smotornyuk authored and amercader committed Feb 14, 2017
1 parent 03b7ebe commit d70db78
Showing 1 changed file with 43 additions and 4 deletions.
47 changes: 43 additions & 4 deletions ckanext/datastore/logic/action.py
@@ -1,9 +1,10 @@
import logging
import json

import pylons
import sqlalchemy

import ckan.lib.base as base
import ckan.lib.search as search
import ckan.lib.navl.dictization_functions
import ckan.logic as logic
import ckan.plugins as p
Expand Down Expand Up @@ -147,9 +148,47 @@ def datastore_create(context, data_dict):
log.debug(
'Setting datastore_active=True on resource {0}'.format(resource.id)
)
p.toolkit.get_action('resource_patch')(
context,
{'id': data_dict['resource_id'], 'datastore_active': True})
# issue #3245: race condition
update_dict = {'datastore_active': True}

# get extras(for entity update) and package_id(for search index update)
res_query = model.Session.query(
model.resource_table.c.extras,
model.resource_table.c.package_id
).filter(
model.Resource.id == data_dict['resource_id']
)
extras, package_id = res_query.one()

# update extras in database for record and its revision
extras.update(update_dict)
res_query.update({'extras': extras}, synchronize_session=False)

model.Session.query(model.resource_revision_table).filter(
model.ResourceRevision.id == data_dict['resource_id'],
model.ResourceRevision.current is True
).update({'extras': extras}, synchronize_session=False)

model.Session.commit()

# get package with updated resource from solr
# find changed resource, patch it and reindex package
psi = search.PackageSearchIndex()
solr_query = search.PackageSearchQuery()
q = {
'q': 'id:"{0}"'.format(package_id),
'fl': 'data_dict',
'wt': 'json',
'fq': 'site_id:"%s"' % config.get('ckan.site_id'),
'rows': 1
}
for record in solr_query.run(q)['results']:
solr_data_dict = json.loads(record['data_dict'])
for resource in solr_data_dict['resources']:
if resource['id'] == data_dict['resource_id']:
resource.update(update_dict)
psi.index_package(solr_data_dict)
break

result.pop('id', None)
result.pop('private', None)
Expand Down

0 comments on commit d70db78

Please sign in to comment.