<aside> <img src="notion://custom_emoji/092854f7-d045-4002-9cb8-706c5d2d1d0d/24447e64-2468-8012-b133-007a33d00653" alt="notion://custom_emoji/092854f7-d045-4002-9cb8-706c5d2d1d0d/24447e64-2468-8012-b133-007a33d00653" width="40px" />

The calendar module in the TANAY API performs selective, one-way, periodic sync from a private Notion DB to a public Google Calendar.

</aside>

Source code & README

Behavior

The calendar module is called in a sync job, reading our ‣ notion DB for any changes with the public Google Calendar, and then reconciling by deleting/modifying/adding events in the GCal as necessary. This behavior is very tightly coupled to the existence of particular properties for each event in the notion DB, so this can be prone to breakage if we’re not careful about it (check the source code for specific info on these properties).

TANAY API-side cron vs Notion-side automation

We tried using the automation feature for Notion DBs, setting it up to POST to an endpoint in the TANAY API upon any modification to an event. But this feature sucks. If it fails in calling the target endpoint, it just shuts off for good. That means if TANAY API is down, the webhook will silently disable, and we wouldn’t know until we check it. OTOH, the behavior of the cron is completely under our control.

Where is source of truth vs point of persistence?

The TANAY API is the source of truth for all information, including events data, so clients like the public website (https://thesoda.io/) pulls event data from there. At the moment, we don’t persist event data in the TANAY API DB, so querying event data from it essentially proxies to the notion DB (with a cache in front (15-min TTL at time of writing) for low-latency and preventing throttling from Notion). The simplicity of this approach is preferable to adding an extra step of dumping the event data into a DB in the TANAY API (which brings the extra maintenance burden of potential migrations, backups, etc.)

Architecture

architecture-beta
		group api(cloud)[TANAY API]
		
    service db(internet)[Google Calendar]
    service vps(server)[VPS via Hostinger] in api
    service ui(database)[Notion DB]
    service website(internet)[Public Website]

    vps:R --> L:db
    vps:L --> R:ui
    website:B --> T:vps