def _do_update(model_instance, base_qs, using, pk_val, values, update_fields, forced_update): version_field = model_instance._concurrencymeta.field old_version = get_revision_of_object(model_instance) if not version_field.model._meta.abstract: if version_field.model is not base_qs.model: return func(model_instance, base_qs, using, pk_val, values, update_fields, forced_update) for i, (field, _1, value) in enumerate(values): if field == version_field: new_version = field._get_next_version(model_instance) values[i] = (field, _1, new_version) field._set_version_value(model_instance, new_version) break if values: if (model_instance._concurrencymeta.enabled and conf.ENABLED and not getattr(model_instance, '_concurrency_disabled', False) and old_version): filter_kwargs = {'pk': pk_val, version_field.attname: old_version} updated = base_qs.filter(**filter_kwargs)._update(values) >= 1 if not updated: version_field._set_version_value(model_instance, old_version) updated = conf._callback(model_instance) else: filter_kwargs = {'pk': pk_val} updated = base_qs.filter(**filter_kwargs)._update(values) >= 1 else: updated = base_qs.filter(pk=pk_val).exists() return updated
def _select_lock(model_instance, version_value=None): if (not conf.ENABLED): return version_field = model_instance._concurrencymeta.field value = version_value or getattr(model_instance, version_field.name) is_versioned = value != version_field.get_default() if model_instance.pk is not None and is_versioned: kwargs = {'pk': model_instance.pk, version_field.name: value} entry = model_instance.__class__._base_manager.filter(**kwargs) if not entry: logger.debug("Conflict detected on `{0}` pk:`{0.pk}`, " "version `{1}` not found".format(model_instance, value)) conf._callback(model_instance)
def _do_update(model_instance, base_qs, using, pk_val, values, update_fields, forced_update): version_field = model_instance._concurrencymeta.field old_version = get_revision_of_object(model_instance) if not version_field.model._meta.abstract: if version_field.model is not base_qs.model: return func(model_instance, base_qs, using, pk_val, values, update_fields, forced_update) for i, (field, _1, value) in enumerate(values): if field == version_field: if (model_instance._concurrencymeta.increment and not getattr(model_instance, '_concurrency_disable_increment', False)): new_version = field._get_next_version(model_instance) values[i] = (field, _1, new_version) field._set_version_value(model_instance, new_version) # else: # new_version = old_version break # This provides a default if either (1) no values were provided or (2) we reached this code as part of a # create. We don't need to worry about a race condition because a competing create should produce an # error anyway. updated = base_qs.filter(pk=pk_val).exists() # This second situation can occur because `Model.save_base` calls `Model._save_parent` without relaying # the `force_insert` flag that marks the process as a create. Eventually, `Model._save_table` will call # this function as-if it were in the middle of an update. The update is expected to fail because there # is no object to update and the caller will fall back on the create logic instead. We need to ensure # the update fails (but does not raise an exception) under this circumstance by skipping the concurrency # logic. if values and updated: if (model_instance._concurrencymeta.enabled and conf.ENABLED and not getattr( model_instance, '_concurrency_disabled', False) and (old_version or not conf.IGNORE_DEFAULT)): filter_kwargs = { 'pk': pk_val, version_field.attname: old_version } updated = base_qs.filter( **filter_kwargs)._update(values) >= 1 if not updated: version_field._set_version_value( model_instance, old_version) updated = conf._callback(model_instance) else: filter_kwargs = {'pk': pk_val} updated = base_qs.filter( **filter_kwargs)._update(values) >= 1 return updated
def _select_lock(model_instance, version_value=None): version_field = model_instance.RevisionMetaInfo.field value = version_value or getattr(model_instance, version_field.name) is_versioned = value != version_field.get_default() if model_instance.pk is not None and is_versioned: kwargs = {'pk': model_instance.pk, version_field.name: value} alias = router.db_for_write(model_instance) NOWAIT = connections[alias].features.has_select_for_update_nowait entry = model_instance.__class__.objects.select_for_update(nowait=NOWAIT).filter(**kwargs) if not entry: logger.debug("Conflict detected on `{0}` pk:`{0.pk}`, " "version `{1}` not found".format(model_instance, value)) if conf.POLICY & CONCURRENCY_POLICY_CALLBACK: conf._callback(model_instance) else: raise RecordModifiedError(_('Record has been modified or no version value passed'), target=model_instance) elif is_versioned and conf.SANITY_CHECK and model_instance._revisionmetainfo.sanity_check: raise InconsistencyError(_('Version field is set (%s) but record has not `pk`.') % value)
def _select_lock(model_instance, version_value=None): if not conf.ENABLED: return version_field = model_instance._concurrencymeta._field value = version_value or getattr(model_instance, version_field.name) is_versioned = value != version_field.get_default() if model_instance.pk is not None and is_versioned: kwargs = {'pk': model_instance.pk, version_field.name: value} if conf.PROTOCOL == 1 and conf.USE_SELECT_FOR_UPDATE: alias = router.db_for_write(model_instance) NOWAIT = connections[alias].features.has_select_for_update_nowait entry = model_instance.__class__._base_manager.select_for_update(nowait=NOWAIT).filter(**kwargs) else: entry = model_instance.__class__._base_manager.filter(**kwargs) if not entry: logger.debug("Conflict detected on `{0}` pk:`{0.pk}`, " "version `{1}` not found".format(model_instance, value)) conf._callback(model_instance)
def _select_lock(model_instance, version_value=None): version_field = model_instance.RevisionMetaInfo.field value = version_value or getattr(model_instance, version_field.name) is_versioned = value != version_field.get_default() if model_instance.pk is not None and is_versioned: kwargs = {'pk': model_instance.pk, version_field.name: value} alias = router.db_for_write(model_instance) NOWAIT = connections[alias].features.has_select_for_update_nowait entry = model_instance.__class__.objects.select_for_update( nowait=NOWAIT).filter(**kwargs) if not entry: logger.debug("Conflict detected on `{0}` pk:`{0.pk}`, " "version `{1}` not found".format( model_instance, value)) if conf.POLICY & CONCURRENCY_POLICY_CALLBACK: conf._callback(model_instance) else: raise RecordModifiedError( _('Record has been modified or no version value passed'), target=model_instance) elif is_versioned and conf.SANITY_CHECK and model_instance._revisionmetainfo.sanity_check: raise InconsistencyError( _('Version field is set (%s) but record has not `pk`.') % value)
def _do_update(model_instance, base_qs, using, pk_val, values, update_fields, forced_update): version_field = model_instance._concurrencymeta.field old_version = get_revision_of_object(model_instance) if not version_field.model._meta.abstract: if version_field.model is not base_qs.model: return func(model_instance, base_qs, using, pk_val, values, update_fields, forced_update) for i, (field, _1, value) in enumerate(values): if field == version_field: if (model_instance._concurrencymeta.increment and not getattr(model_instance, '_concurrency_disable_increment', False)): new_version = field._get_next_version(model_instance) values[i] = (field, _1, new_version) field._set_version_value(model_instance, new_version) # else: # new_version = old_version break # This provides a default if either (1) no values were provided or (2) we reached this code as part of a # create. We don't need to worry about a race condition because a competing create should produce an # error anyway. updated = base_qs.filter(pk=pk_val).exists() # This second situation can occur because `Model.save_base` calls `Model._save_parent` without relaying # the `force_insert` flag that marks the process as a create. Eventually, `Model._save_table` will call # this function as-if it were in the middle of an update. The update is expected to fail because there # is no object to update and the caller will fall back on the create logic instead. We need to ensure # the update fails (but does not raise an exception) under this circumstance by skipping the concurrency # logic. if values and updated: if (model_instance._concurrencymeta.enabled and conf.ENABLED and not getattr(model_instance, '_concurrency_disabled', False) and (old_version or not conf.IGNORE_DEFAULT)): filter_kwargs = {'pk': pk_val, version_field.attname: old_version} updated = base_qs.filter(**filter_kwargs)._update(values) >= 1 if not updated: version_field._set_version_value(model_instance, old_version) updated = conf._callback(model_instance) else: filter_kwargs = {'pk': pk_val} updated = base_qs.filter(**filter_kwargs)._update(values) >= 1 return updated