Sync after Google error erroneous when retried
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.
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.
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)))))))))
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.
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?
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)))))
great, thanks.