Skip to content

Commit

Permalink
Extend IDomainObjectModification
Browse files Browse the repository at this point in the history
Currently the notify signal is sent before the database commit has occurred. It
is not possible to listen for modification events and know that the changes
have made it to the database. This can lead to a race condition if you try to
get a record from the database.

For an example see:

ckan/ckanext-archiver#6

This extension of the interface would allow notification after the database
commit has occurred.
  • Loading branch information
morty committed Jul 21, 2014
1 parent 3dde3be commit 3282b12
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
24 changes: 20 additions & 4 deletions ckan/model/modification.py
Expand Up @@ -32,7 +32,12 @@ def notify_observers(self, func):


def before_commit(self, session):
self.notify_observers(session, self.notify)

def after_commit(self, session):
self.notify_observers(session, self.notify_after_commit)

def notify_observers(self, session, method):
session.flush()
if not hasattr(session, '_object_cache'):
return
Expand All @@ -44,13 +49,13 @@ def before_commit(self, session):

for obj in set(new):
if isinstance(obj, (_package.Package, resource.Resource)):
self.notify(obj, domain_object.DomainObjectOperation.new)
method(obj, domain_object.DomainObjectOperation.new)
for obj in set(deleted):
if isinstance(obj, (_package.Package, resource.Resource)):
self.notify(obj, domain_object.DomainObjectOperation.deleted)
method(obj, domain_object.DomainObjectOperation.deleted)
for obj in set(changed):
if isinstance(obj, resource.Resource):
self.notify(obj, domain_object.DomainObjectOperation.changed)
method(obj, domain_object.DomainObjectOperation.changed)
if getattr(obj, 'url_changed', False):
for item in plugins.PluginImplementations(plugins.IResourceUrlChange):
item.notify(obj)
Expand All @@ -69,7 +74,7 @@ def before_commit(self, session):
if package and package not in deleted | new:
changed_pkgs.add(package)
for obj in changed_pkgs:
self.notify(obj, domain_object.DomainObjectOperation.changed)
method(obj, domain_object.DomainObjectOperation.changed)


def notify(self, entity, operation):
Expand All @@ -82,3 +87,14 @@ def notify(self, entity, operation):
# We reraise all exceptions so they are obvious there
# is something wrong
raise

def notify_after_commit(self, entity, operation):
for observer in plugins.PluginImplementations(
plugins.IDomainObjectModification):
try:
observer.notify_after_commit(entity, operation)
except Exception, ex:
log.exception(ex)
# We reraise all exceptions so they are obvious there
# is something wrong
raise
3 changes: 3 additions & 0 deletions ckan/plugins/interfaces.py
Expand Up @@ -185,6 +185,9 @@ class IDomainObjectModification(Interface):
def notify(self, entity, operation):
pass

def notify_after_commit(self, entity, operation):
pass


class IResourceUrlChange(Interface):
"""
Expand Down

0 comments on commit 3282b12

Please sign in to comment.