org-caldav icon indicating copy to clipboard operation
org-caldav copied to clipboard

Sync after Google error erroneous when retried

Open rgemulla opened this issue 8 years ago • 6 comments

When synching calendars via Google, I sometimes get a "401 Unauthorized" error. (This may be because the oauth2 access token expired.)

When org-caldav-retry-attempts=1, org-caldav stops the sync after such an error. If I start the sync again manually, everything works flawlessly.

When org-caldav-retry-attempts>1, however, org-caldav retries to sync after the 401 error. In this case, the 401 error disappears, but another issue pops up. In particular, org-caldav seems to receive an empty event list and thus asks me for every item in my calender whether I want to remove it. Even aborting and restarting the sync yields the same error. If Emacs is restarted, everything works fine again.

Since everything works when org-caldav-retry-attempts=1, I guess this indicates some bug in the way retries are handled.

rgemulla avatar Aug 16 '17 19:08 rgemulla

One more piece of information. If run

(progn 
  (org-caldav-sync)
  (org-caldav-sync))

and the first sync fails, the second sync leads to the problem mentioned above: org-caldav asks to delete every calendar entry.

If I run

(progn 
  (org-caldav-sync)
  (sleep-for 1)
  (org-caldav-sync))

instead and the first sync fails, the second one goes through without any problems. This suggests that a delay between successive retries is needed. Perhaps adding a customizable option for retry delays to org-caldav might be useful.

rgemulla avatar Aug 30 '17 15:08 rgemulla

For the record, this fixes this problem:

(defun rg/org-caldav-sync ()
  (interactive)
  (let ((message-log-max))
    (message "Synchronizing calendars..."))
  (let ((remaining-retries 3))
    (while (> remaining-retries 0)
      (condition-case ex                  ;
          (progn
            (org-caldav-sync)
            (setq remaining-retries 0)) ;; all done
        ('error
         (progn 
           (if (string-match-p "https://apidata.googleusercontent.com/caldav/v2.*401 Unauthorized"
                               (error-message-string ex))
               (progn
                 (kill-matching-buffers-no-ask
                  "^ \\*http apidata\\.googleusercontent\\.com:443\\*.*" t)
                 (let ((message-log-max))
                   (message "Retrying to synchronize calenders..."))
                 ;; There was a synchronization error, most likely due to an
                 ;; expired oauth2 access token. Trying again should work fine.
                 (sleep-for 1)
                 (setq remaining-retries (- remaining-retries 1)))
             (error "%s" (error-message-string ex)))))))))

rgemulla avatar Sep 04 '17 20:09 rgemulla

Thank you for this. I also experience the problem of being asked to delete all of my org entries. I did not realise that restarting Emacs would solve the problem (it did just now for me). I will try your solution sometime soon, when I need to.

sje30 avatar Sep 07 '17 18:09 sje30

just tried your solution... but I see kill-matching-buffers-no-ask is not defined; I guess what it does, but which defun do you use?

sje30 avatar Sep 13 '17 20:09 sje30

Yes, I forgot to include this function. Here it is:

(defun kill-matching-buffers-no-ask (regexp &optional internal-too)
  "Kill buffers whose name matches the specified REGEXP without asking for confirmation.
The optional second argument indicates whether to kill internal
buffers too."
  (interactive "sKill buffers matching this regular expression: \nP")
  (dolist (buffer (buffer-list))
    (let ((name (buffer-name buffer)))
      (when (and name (not (string-equal name ""))
                 (or internal-too (/= (aref name 0) ?\s))
                 (string-match regexp name))
        (kill-buffer buffer)))))

rgemulla avatar Sep 13 '17 20:09 rgemulla

great, thanks.

sje30 avatar Sep 13 '17 21:09 sje30