Resolving CUD conflicts
===
Rhoconnect CUD queue and potential conflicts
---
By design, your Rhoconnect application supports parallel dispatching of the multiple client's requests via the asynchronous Resque jobs. This scenario can lead to a situation where two or more clients will try to perform CUD operations at the same time, potentially creating the race condition. For example, this can happen when two users will try to insert or delete the same record simultaneously.
To handle this situation , Rhoconnect uses the CUD queue, which is being dispatched continuously. You can inspect this queue before the CUD operation is called and mark the conflicting records for special processing. To do this, you need to override the Source Adapter `validate` method that is called before the CUD queue is dispatched. This method has the following parameters:
String |
operation |
CUD operation marker, one of three: create, update, or delete |
Array Of Record Hashes |
cud_queue |
CUD queue consisting of CUD request hashes, ordered from oldest to newest. Each entry in the queue contains a hash of CUD records to process. (Each CUD client request can contain more than one record |
Array Of Client Ids |
client_queue |
This array is used to map the CUD request in the above queue to a corresponding client ID. i.e. CUD_queue[N] request was issued by client_queue[N] client. Please note that there may be several entries from the same client - if they came separately in time |
Below you can see the example of the `validate` method parameters indicating two create requests containing the conflicting records:
:::ruby
client_1 = 'cid_1'
cud_request_1 = { 'temp_cid1_1' => {'name' => 'iPhone'}, 'temp_cid1_2' => {'name' => 'Android'}}
client_2 = 'cid_2'
cud_request_2 = { 'temp_cid2_1' => {'name' => 'iPhone'}} # this record seems to be the duplicate of the record 'temp_cid1_1'
operation = 'create'
cud_queue = [ cud_request_1, cud_request_2 ]
client_ids = [ client_1, client_2 ]
Detecting the conflict and forcing an error
---
Using the above `validate` method you can iterate through the queue and detect CUD conflicts based on the desired application logic. Once the conflicting record is found (for example, duplicate create request), you need to mark it by inserting the conflicting record parameters into the special hash structure that is returned by the `validate` method:
:::ruby
def validate(operation, cud_queue, client_ids)
resulting_meta_hash = {}
# iterating through the queue
cud_queue.each_with_index do |cud_request, index|
cud_request_client = client_ids[index]
# iterating through the request records
cud_request.each do |record_id, record_hash|
# ... detecting the conflict here ....
# !!! found a conflict - force an error
error_record_id = record_id
record_meta_data = { error_record_id => { :error => 'my_error_string: conflict is detected!!!' }}
resulting_meta_hash[index] ||= {}
resulting_meta_hash[index].merge!(record_meta_data)
end
end
resulting_meta_hash
end
Once the `validate` method returns non-empty validation metadata hash structure, it will be used in processing the CUD queue. All marked records will not be processed, but instead an error will be sent back to the originating client with the user-provided error message.