Example #1
0
        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
Example #2
0
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)
Example #3
0
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
Example #5
0
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)
Example #6
0
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)
Example #7
0
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)
Example #8
0
        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