Split up the checking resoruce response and adding the (accepted) event to
authorMichael J. Rubinsky <mrubinsk@horde.org>
Mon, 21 Sep 2009 21:59:02 +0000 (17:59 -0400)
committerMichael J. Rubinsky <mrubinsk@horde.org>
Tue, 29 Sep 2009 20:53:57 +0000 (16:53 -0400)
the resource's calendar.

This is needed because we need the event to have a guid when it's added to
the resource's calendar, otherwise they end up with different GUIDs. This also
gives us some protection against an inconsistent state if there were to be an issue
saving the event to storage after it's been added to the resource's calendar.

kronolith/lib/Event.php

index 70d3fab..28dd905 100644 (file)
@@ -322,19 +322,33 @@ abstract class Kronolith_Event
          * inadvertantly getting accepted. (Two simultaneous requests, both
          * return RESPONSE_ACCEPTED from getResponse()) Maybe Horde_Lock?
          */
+        $add_events = array();
         foreach ($this->getResources() as $id => $resourceData) {
             $resource = Kronolith::getDriver('Resource')->getResource($id);
             $response = $resource->getResponse($this);
             if ($response == Kronolith::RESPONSE_ACCEPTED) {
-                $resource->addEvent($this);
+                $add_events[] = $resource;
             }
             $this->addResource($resource, $response);
         }
-
         $this->toDriver();
         $result = $this->getDriver()->saveEvent($this);
-        if (!is_a($result, 'PEAR_Error') &&
-            !empty($GLOBALS['conf']['alarms']['driver'])) {
+        if (is_a($result, 'PEAR_Error')) {
+            return $result;
+        }
+
+        /* Now that the event is definitely commited to storage, we can add the
+         * event to each resource that has accepted. Not very efficient, but
+         * this also solves the problem of not having a GUID for the event until
+         * after it's saved. If we add the event to the resources calendar
+         * before it is saved, they will have different GUIDs, and hence no
+         * longer refer to the same event.
+         */
+        foreach ($add_events as $resource) {
+            $resource->addEvent($this);
+        }
+
+        if (!empty($GLOBALS['conf']['alarms']['driver'])) {
             $alarm = $this->toAlarm(new Horde_Date($_SERVER['REQUEST_TIME']));
             if ($alarm) {
                 $alarm['start'] = new Horde_Date($alarm['start']);