Skip to content

Commit

Permalink
Accounted for a possible race condition in model state rendering.
Browse files Browse the repository at this point in the history
  • Loading branch information
charettes committed Jan 2, 2016
1 parent b3d75fb commit 2940322
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
18 changes: 13 additions & 5 deletions mutant/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ def clear_opts_related_cache(model_class):
Clear the specified model and its children opts related cache.
"""
opts = model_class._meta
children = [
related_object.model
for related_object in opts.get_all_related_objects()
if related_object.field.rel.parent_link
]
if hasattr(opts, '_related_objects_cache'):
children = [
related_object.model
for related_object in opts.get_all_related_objects()
if related_object.field.rel.parent_link
]
else:
children = []
for attr in _opts_related_cache_attrs:
try:
delattr(opts, attr)
Expand Down Expand Up @@ -77,6 +80,11 @@ def bulk_update(self):
self.ready = ready
self.clear_cache()

def get_model(self, app_label, model_name=None):
if model_name is None:
app_label, model_name = app_label.split('.')
return self.all_models[app_label][model_name]

def render_multiple(self, model_states):
# We keep trying to render the models in a loop, ignoring invalid
# base errors, until the size of the unrendered models doesn't
Expand Down
2 changes: 1 addition & 1 deletion mutant/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def get_model_state(cls):

@classmethod
def render_state(cls):
apps = StateApps([], {})
state = cls.get_model_state()
model_states = {(state.app_label, state.name): state}
for _name, field in state.fields:
Expand All @@ -56,6 +55,7 @@ def render_state(cls):
cls._meta.apps.get_model(base), exclude_rels=True
)
model_states[base_model_state.app_label, base_model_state.name] = base_model_state
apps = StateApps([], {})
apps.render_multiple(model_states.values())
return apps.all_models[state.app_label][state.name.lower()]

Expand Down
7 changes: 6 additions & 1 deletion mutant/models/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,12 @@ def construct(self, force_create=False, existing_model_class=None):
remove_from_app_cache(existing_model_class)
existing_model_class.mark_as_obsolete()

model_class = state.render(apps)
try:
model_class = state.render(apps)
except RuntimeError:
# Account for race conditions between the removal from the apps
# and the rendering of the new state.
return apps.get_model(state.app_label, state.name)
model_class._checksum = checksum
for attr, value in attrs.items():
setattr(model_class, attr, value)
Expand Down

0 comments on commit 2940322

Please sign in to comment.