(Difference between revisions)
Jump to: navigation, search

OVirt-DB-Issues/compensation

(What changes are logged)
(When using compensation at command)
 
Line 66: Line 66:
 
Add at DbFacade.mapEntityToDAO an entry that maps the entity to its DAO<br>
 
Add at DbFacade.mapEntityToDAO an entry that maps the entity to its DAO<br>
  
=== When using compensation at command ===
+
=== Using compensation at a command ===
 
Implement a CTOR that takes a commandId as parameter for Compensation after server restart<br>
 
Implement a CTOR that takes a commandId as parameter for Compensation after server restart<br>
 
Annotate the command with @NonTransactiveCommandAttribute(forceCompensation=true) in order to eliminate creation of transaction that wraps the entire command, and in order to create a new CompensationContext<br>
 
Annotate the command with @NonTransactiveCommandAttribute(forceCompensation=true) in order to eliminate creation of transaction that wraps the entire command, and in order to create a new CompensationContext<br>
 
Remember to use short transactions as possible<br>
 
Remember to use short transactions as possible<br>
 
For the last update part of the command – compensation code is not required – the transaction will rollback this part, if needed<br>
 
For the last update part of the command – compensation code is not required – the transaction will rollback this part, if needed<br>

Latest revision as of 18:08, 22 August 2012

Contents

[edit] Compensation mechanism

[edit] What is compensation all about?

Isolation level: what changes of a transaction T are exposed to other transactions

Postgres does not implement the READ-UNCOMMITTED isolation level. We have to notify the clients ASAP on entities that are changing status, this implies committing database changes ASAP before the asynchronous tasks associated with the relevant command are complete and in order to keep transactions as short as possible, create a entity change log which we can use to revert the changes if any asynchronous task fails.

The process of logging those changes and roll back them if something fails is called compensation.

[edit] Compensation change log

Change log is recorded in the database in the business_entity_snapshot table

     Column      |          Type          | Modifiers 
-----------------+------------------------+-----------
id              | uuid                   | not null
command_id      | uuid                   | not null
command_type    | character varying(256) | not null
entity_id       | character varying(128) | 
entity_type     | character varying(128) | 
entity_snapshot | text                   | 
snapshot_class  | character varying(128) | 
snapshot_type   | integer                | 
insertion_order | integer                |

Each command may affect multiple entities
A parent command may call other commands as part of its execution.

[edit] What changes are logged?

 Insertion – the ID of the new entity (compensation = delete entity by Id)
 Deletion – the deleted entity (compensation = re-insertion of the entity)
 Update – the entity before the change (compensation = update entity with “old values”)
 UpdateStatus – the status before change (compensation = update entity with “old status” - this is an optimization)

[edit] BusinessEntity interface

All compensatable entities must implement BusinessEntity interface
This interface exposes the get/set of the entity ID
The business entity must be serializable, so does the type of the ID in order to log the changes

[edit] BusinessEntitySnapshot

 CHANGED_ENTITY – update/delete
 NEW_ENTITY_ID – insert
 CHANGED_STATUS_ONLY – update status 

[edit] CompensationContext

CompensationContext provides the API for adding entries to the “change log” and to flush the “change log” to DB

[edit] When to compensate?

 Exception in execution has occurred
 The status of the transaction is inactive (if code is run in transaction)
 Failure in execution
 Server restart with existing entries at business_entity_snapshot

[edit] Example: ActivateStorageDomainCommand

ChangeStorageDomainStatusInTransaction – change storage domain status to LOCKED, in a transaction + compensation code (pay attention – the code is run in a transaction scope which is comitted prior to the next step)
ActivateStorageDomainCommand VDS command is executed (this takes some time)
If VDS command successful

 Perform some stuff
 Change storage domain status to active (in transaction  + compensation code)
 Perform some other stuff

[edit] Usage

Make sure your entity implements BusinessEntitySnapshot
Make sure its DAO implements ModificationDao and StatusAwareDao (optional, for status changes optimization)
Add at DbFacade.mapEntityToDAO an entry that maps the entity to its DAO

[edit] Using compensation at a command

Implement a CTOR that takes a commandId as parameter for Compensation after server restart
Annotate the command with @NonTransactiveCommandAttribute(forceCompensation=true) in order to eliminate creation of transaction that wraps the entire command, and in order to create a new CompensationContext
Remember to use short transactions as possible
For the last update part of the command – compensation code is not required – the transaction will rollback this part, if needed