Jump to: navigation, search

Difference between revisions of "Designate/Blueprints/Bulk Actions"

(Blueprint for Bulk Actions, in a couple of phases.)
 
(Overview)
Line 1: Line 1:
 
== Overview ==
 
== Overview ==
  
A user should be able to create, modify, and delete multiple zones (and eventually records).  
+
A user should be able to create, modify, and delete multiple resources.  
  
 
There are many use cases for applying multiple operations at once.  
 
There are many use cases for applying multiple operations at once.  

Revision as of 20:28, 20 January 2014

Overview

A user should be able to create, modify, and delete multiple resources.

There are many use cases for applying multiple operations at once. For example:

  • Zone level TTLs for multiple zones may need updating for a migration.
  • Account/tenant cleanup is underway and zones need to be purged.
  • A new user adding all of their zones quickly.

Phase 1: Making the Database Interaction More Transactional

The database interactions with storage should work in the following way:

  1. Begin the transaction
  2. Execute the appropriate data manipulations to accomplish the task at hand (ie Create a Zone)
  3. If no errors occur then commit the transaction and end it
  4. If errors occur then rollback the transaction and end it


SQLAlchemy supports transactions via sessions so the SQLAlchemy driver will need to be updated to use these operations.

That should consist of:

   def begin(self):
       self.session.begin(subtransactions=True)
   def commit(self):
      self.session.commit()
   def rollback(self):
      self.session.rollback()

To be called in designate/storage/api.py using "self.storage.begin()". Subtransactions must be used in begin() because the session itself is already part of a transaction.

This will allow the elimination of the manual rollbacks in the storage/api.py by utilizing the built-in rollback capabilities in SQLAlchemy. For example:

   @contextlib.contextmanager
   def create_domain(self, context, values):
       domain = self.storage.create_domain(context, values)
       try:
           yield domain
       except Exception:
           with excutils.save_and_reraise_exception():
               self.storage.delete_domain(context, domain['id'])

Will change to:

   @contextlib.contextmanager
   def create_domain(self, context, values):
       self.storage.begin()
       domain = self.storage.create_domain(context, values)
       try:
           yield domain
       except Exception:
           with excutils.save_and_reraise_exception():
               self.storage.rollback()
       else:
           self.storage.commit()


Phase 2: Supporting Bulk Actions

Note: This needs to be fleshed out more and discussed.

There are a couple of different ways this could be done.

Here are a few of different ways the API calls could look. There are pretty much endless possiblities in this regard that will have to be discussed.

http://xx.xx.x.x:9001/v2/zones POST

{
  "zone": {
    "name": "example.org.",
    "email": "joe@example.org",
    "ttl": 7200
  },
  "zone": {
    "name": "example2.org.",
    "email": "joe@example.org",
    "ttl": 7200
  }
} 
OR
{
   "zones": {
       "email": "joe@example.org",
       "ttl": 7200,
       "names": [
           {
               "name": "example.org."
           },
           {
               "name": "example2.org."
           }
       ]
   }
} 
OR
{
     example.org
     example2.org
}


Some of the operations will no doubt have their own blueprints and all that, but these two options are just two schools of thought on how bulk actions could be accomplished.

Option 1

Expand the new transactions to be called one at a time.

So whatever the implementation of the API call, the methods for bulk actions would call the ones for the single actions one at a time, and report the actions back. This is essentially equivalent to making a script that would perform the bulk action you require.

The option would allow for some of the requests to succeed and some to fail. This would be reported to the user. It would then be their prerogative to fix whatever issue caused them to fail, or try again if it was Designates fault.

Option 2

The "all or nothing" approach.

A bulk action will attempt to be applied, but if any part of it fails, the entire action is invalid and everything is rolled back.

On a failure, an error message would be passed back to the user telling them what exactly failed, and they could retry or reconsider.

This option prevents users from getting to a state they haven't desired. A user would never try to add 100 zone and end up with 77 added in this scenario. It minimizes risk of getting into a situation that changes many things, but doesn't accomplish the original intention of the user should some things fail.