Ryan, You are completely right about the atomic operation. The below works well with a hard coded value, but I need to insert $quantity since that will vary based on the adjustment needed from an order or stock being added. I'm stuck with the code change into the literal value there.
$this->updateAll( array('Venue.inventory' => 'Venue.inventory+$quantity'), array('Venue.id' => $id)); Thanks, Brian On Mar 1, 2:06 pm, Ryan Schmidt <google-2...@ryandesign.com> wrote: > On Mar 1, 2011, at 12:46, Ryan Schmidt wrote: > > > > > On Mar 1, 2011, at 11:35, lirc201 wrote: > > >> I like the example on the weblink which is just using MySQL > >> functionality, it is very clever. Thanks for the help and push. My > >> code is working! I did like the security tricks I discovered for my > >> updates below to only pass a field list. > > >> function updateInventory($id, $quantity) { > >> $inv = $this->getQuantity($id); <- function is in the > >> same model > >> $this->data['Model']['id'] = $id; > >> $this->data['Model']['inventory'] = $inv + $quantity; > >> if($this->save($this->data, array( > >> 'validate' => 'false', > >> 'fieldList' => array('id', > >> 'inventory')))) { > >> ... logic for return values ... > >> } > >> } > > > This is not atomic. Between the line where you get the current quantity and > > the line where you save the updated quantity, someone else might have > > updated the quantity, and you'd be wiping out their change. Consider two > > managers simultaneously adding 5 to the inventory of the same item. The > > expected result would be that in the end the inventory is incremented by > > 10, but because of the race condition in your code, it might only be > > incremented by 5. > > The problem is more apparent if you think about the case of a customer buying > an item on your site and decreasing the inventory. > > Let's say your inventory for item id 3 is 10, and you have two users about to > buy one each of item id 3. Both users happen to click the Buy button at the > same instant, which will cause the method updateInventory(3, -1) to be called > for each user. If this method runs at the same time for both users, then for > both users getQuantity() will return 10, in both cases you'll add $quantity > to it, thereby decreasing it by one, and in both cases you'll save 9 to the > database -- even though two users have successfully bought the item and the > inventory should now be 8. Clearly this will be a problem as your database > might say you have more quantity than you actually do and customers will try > to buy product you no longer have. > > The solution is to use a single atomic SQL UPDATE statement, as I showed > earlier (or rather, the CakePHP equivalent of that), or use an SQL > transaction (and ensure your database supports transactions -- for example > for MySQL, you'd use InnoDB tables instead of MyISAM). -- Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions. To unsubscribe from this group, send email to cake-php+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php