<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/tests/test-calendar-sync--batch-wait.el, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-08-03T14:39:08+00:00</updated>
<entry>
<title>fix(calendar-sync): run the sync from a timer instead of the agenda hook</title>
<updated>2026-08-03T14:39:08+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-03T14:39:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=eb0c2191b77e795cca7884e0690ea51c515527fd'/>
<id>urn:sha1:eb0c2191b77e795cca7884e0690ea51c515527fd</id>
<content type='text'>
The hourly timer armed itself from org-agenda-mode-hook, so a session where
I never opened the agenda never synced at all. After a reboot that is every
session until the first agenda call. I found it with all three calendar
files still frozen at the pre-reboot write, five hours stale.

The deferral had a real reason. Feed URLs behind :secret-host live in
authinfo.gpg, and starting at load would prompt for a passphrase on a cold
gpg-agent. The cost was worse than what it bought.

A user timer owns the schedule now, every ten minutes.
calendar-sync-auto-start defaults to nil so the editor no longer arms its
own. scripts/calendar-sync-run is the batch entry point, and it blocks
until every calendar leaves the syncing state. The pipeline is asynchronous
end to end, so a batch Emacs that returns early exits zero having written
nothing.

Installing it on a machine that resolves its feeds through :secret-host
surfaced two bugs the inline-url machine could never show:

- cj/auth-source-secret-value called auth-source-search behind nothing but
  a declare-function, which quiets the compiler and loads nothing. An
  interactive Emacs always has auth-source in by the time anyone calls, so
  the omission stayed invisible until a batch -Q sync died on a void
  function. The require is guarded on fboundp. An unconditional one reloads
  auth-source over whatever is already there, which replaced a caller's
  stubbed search mid-call and sent an existing test out to the real
  authinfo.

- A synchronous failure in one calendar aborted the whole loop. The async
  callbacks record their own failures, but they never run when the error
  lands before a process starts. Resolving a :secret-host feed signals
  outright on a cold agent. Failures are contained per calendar now, so one
  bad feed no longer costs the other two.

A failed row prints the reason it recorded. Batch Emacs discards the
*Messages* buffer the interactive path logs to, so without it the journal
shows only "error", with no way to tell a cold agent from a revoked token.
</content>
</entry>
</feed>
