Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore transactions for data import #480

Conversation

thauk-copperleaf
Copy link
Contributor

Commit e9869f0 added the @atomic decorator to Resource.import_data(), which resulted in every import being performed atomically, irrespective of the value of use_transactions.

This restores the sematics for use_transactions to be used correctly, but still wraps the call to Resource.import_data() with the transaction.atomic context manager when necessary, to ensure atomic behaviour for existing clients of the library.

To achieve this, Resource.import_data() is refactored to have an "outer" wrapper to perform the atomicity check, and the remainder of the function as an "inner".

…dle semantics of use_transactions to actually only use a transaction when set to True or when dry_run is True. Set default of use_transactions to True since that is the functional effect of using @atomic, so existing clients of the library are not impacted.
…or IMPORT_EXPORT_USE_TRANSACTIONS to True, set default value for use_transactions to None. Means code will only break for clients who have have set IMPORT_EXPORT_USE_TRANSACTIONS to False but were still expecting atomicity on import_data (i.e. hopefully no one!)
@arj03
Copy link

arj03 commented Jul 12, 2016

This code looks good. Not sure about removing the comments in before_import. Really like the sane defaults of this 👍

@thauk-copperleaf
Copy link
Contributor Author

@arj03 The comments in both before_import() and after_import() either just say what the parameters are (redundant) or make mention of if changes will be rolled back (and that behaviour is now actually dependant on the values of use_transactions and dry_run that are passed into import_data() and happens outside their scope).

@bmihelac
Copy link
Member

Thanks for your work @thauk-copperleaf

I am little concered that this brings some backward incompatible changes:

  1. default IMPORT_EXPORT_USE_TRANSACTIONS is set to True - is there any reason for this
  2. many methods have an additional argument using_transactions. I am thinking if it would be better to move using_transactions to resource constructor.

What do you think?

@thauk-copperleaf
Copy link
Contributor Author

1-- Because import_data() has the @atomic decorator, everything is in a transaction, whether the user has asked for it or not. To preserve this behaviour for existing clients of the library, we set IMPORT_EXPORT_USE_TRANSACTIONS to True.
2-- I just got in this morning, so I'll need some time to think about it as well as resolve the conflicts in the branch 😄

…re-transactions-for-data-import

# Conflicts:
#	import_export/resources.py
@thauk-copperleaf
Copy link
Contributor Author

using_transactions is really just the answer to the question "Are we currently inside an @atomic block?", which is only known inside import_data(), so it can't be assigned only in the resource constructor.

Since the semantics of using_transactions is only relevant within the scope of an import call, there's no reason to make it a property of the Resource class. The natural state of a Resource is orthogonal to how it gets imported.

We pass using_transactions as a parameter next to wherever (the now correct value for) dry_run is being passed, so existing clients can adjust behaviour appropriately.

@thauk-copperleaf
Copy link
Contributor Author

Fixes #411

@arj03
Copy link

arj03 commented Jul 20, 2016

Also fixes #488 :)

@shaggyfrog shaggyfrog merged commit 84ba3f8 into django-import-export:master Aug 16, 2016
@thauk-copperleaf thauk-copperleaf deleted the restore-transactions-for-data-import branch August 16, 2016 21:23
mkurek pushed a commit to mkurek/django-import-export that referenced this pull request Dec 30, 2016
PR django-import-export#480 introduced proper handling of transactions during import, but with additional check if DB engine does support transactions.

When transaction is already in atomic block (for example by using `ATOMIC_REQUESTS` in Django DB conf) and `import_data` performs check if DB support transaction, in some cases (like MySQL), this check tries to call `set_autocommit`, which is forbidden in atomic block. This fix it not to use `supports_transaction` at all (it's not used in whole Django at all either, besides tests) - previously user receives `ImproperlyConfigured` exception - now `transaction.atomic` will go through silently (for example in MyISAM case) or raise another exception to user, but it'll work for all engines that support DB transactions when transaction block is already entered.
mkurek pushed a commit to mkurek/django-import-export that referenced this pull request Dec 30, 2016
PR django-import-export#480 introduced proper handling of transactions during import, but with additional check if DB engine does support transactions.

When transaction is already in atomic block (for example by using `ATOMIC_REQUESTS` in Django DB conf) and `import_data` performs check if DB support transaction, in some cases (like MySQL), this check tries to call `set_autocommit`, which is forbidden in atomic block. This fix it not to use `supports_transaction` at all (it's not used in whole Django at all either, besides tests) - previously user receives `ImproperlyConfigured` exception - now `transaction.atomic` will go through silently (for example in MyISAM case) or raise another exception to user, but it'll work for all engines that support DB transactions when transaction block is already entered.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants