Database Reference
In-Depth Information
query = selector.merge(:state => opts[:from])
physical_item = @inventory.find_and_modify(:query => query,
:update => {'$set' => {:state => opts[:to], :ts => Time.now.utc}})
if physical_item.nil?
raise InventoryFetchFailure
end
items_transitioned << physical_item['_id']
@orders.update({:_id => order_id},
{"$push" => {:item_ids => physical_item['_id']}})
end
rescue Mongo::OperationFailure, InventoryFetchFailure
rollback(order_id, items_transitioned, opts[:from], opts[:to])
raise InventoryFetchFailure, "Failed to add #{selector[:sku]}"
end
items_transitioned.size
end
To t r a n s i t io n s t a t e , e a c h s e l e c t o r g e t s a n e xt r a c o n d i t i o n , {:state => AVAILABLE} , and
then the selector is passed to findAndModify which, if matched, sets a timestamp and
the item's new state. The method then saves the list of items transitioned and updates
the order with the ID of the item just added.
If the findAndModify command fails and returns nil , then you raise an Inventory-
FetchFailure exception. If the command fails because of networking errors, you res-
cue the inevitable Mongo::OperationFailure exception. In both cases, you rescue by
rolling back all the items transitioned thus far and then raise an InventoryFetch-
Failure , which includes the SKU of the item that couldn't be added. You can then res-
cue this exception on the application layer to fail gracefully for the user.
All that now remains is to examine the rollback code:
def rollback(order_id, item_ids, old_state, new_state)
@orders.update({"_id" => order_id},
{"$pullAll" => {:item_ids => item_ids}})
item_ids.each do |id|
@inventory.find_and_modify(
:query => {"_id" => id, :state => new_state},
:update => {"$set" => {:state => old_state, :ts => Time.now.utc}}
)
end
end
You use the $pullAll operator to remove all of the ID s just added to the order's
item_ids array. You then iterate over the list of item ID s and transition each one back
to its old state.
The transition_state method can be used as the basis for other methods that
move items through their successive states. It wouldn't be difficult to integrate this
into the order transition system that you built in the previous subsection. But that
must be left as an exercise for the reader.
Search WWH ::




Custom Search