Srijan Choudhary

Hi, I'm Srijan Choudhary.

I'm a founding member and software engineering leader at GreyOrange, working on disrupting and redefining fulfillment.

I'm interested in software team leadership, functional programming, distributed systems, artificial intelligence, and software infrastructure.

In my free time, I enjoy traveling, running, playing with technology, listening to music, creating music, and reading.

I write here when I have something to share - a personal project, some difficult problem I solved recently, or just an idea.

Take a look at the about page for more details, or follow me on mastodon.

Recent Articles

Recent Notes

Srijan Choudhary Srijan Choudhary
> Reply to mauricerenck/komments

SQLite comment storage (v3) breaks page-cache invalidation (staticache): comments show in Panel but not on cached pages

Summary

Since v3 moved comment storage from inline content-file fields to SQLite, komments no longer triggers Kirby's page-cache invalidation when a comment or webmention changes. On any site that uses a page cache — in particular the official getkirby/staticache — new comments show up in the Panel (which reads the DB live) but never appear on the public page, which keeps serving stale cached HTML until the page's content file happens to be edited for some unrelated reason.

This is effectively a silent regression for anyone who paired komments with a page cache.

Root cause

  • In v2, received comments/webmentions were written into the page's content file. A content-file write is a page change, so Kirby automatically flushed that page's cache and the public page updated on the next request — invalidation came "for free" as a side effect.

  • In v3 with storage.type => 'sqlite', comments are written to the SQLite DB and the content file is never touched. Kirby only invalidates a page's cache entry when the page/model itself changes, so nothing flushes the cache. $page->comments() reads live from the DB on render, but with a page cache active the cached HTML is served without render() ever being called.

Steps to reproduce

  1. Kirby with page caching enabled, e.g. getkirby/staticache (cache.pages.type => 'static').
  2. komments v3 with storage.type => 'sqlite'. Webmentions auto-publish by default; comments via a moderated-then-published flow.
  3. Visit a post once to prime the cache.
  4. Receive a webmention (or publish a comment) for that post.
  5. Panel shows the comment; the public page does not (stale cached HTML). It only corrects itself if the page's content file is later edited.

Expected

Adding, publishing, or removing a comment/webmention for a page should mark that page's cache stale, so the next request re-renders with the current comments.

What already works vs. the gaps

komments already fires hooks integrators can subscribe to for cache invalidation:

  • komments.comment.received

  • komments.comment.replied

  • komments.comment.published (fires on the publish/unpublish toggle, both directions)

But several mutations that change public output fire no event at all, so there is no way to invalidate on them:

  • deleteComment / deleteCommentsInBatch (moderation delete) — no trigger

  • flagComment / flagCommentsInBatch (spam/flag, which can hide a comment) — no trigger

These live under the plugin's api routes, so they also can't be caught via Kirby's route:after hook (that only fires for the front-end router, not the Panel API), and there is no API-level hook. So today a delete or spam-flag can't be reliably detected by an integrator.

Suggestions (any one would help)

  1. Emit a complete set of mutation hooks. Add triggers for delete and flag and their batch variants — e.g. komments.comment.deleted / komments.comment.flagged — mirroring the existing received / published / replied events. A complete event surface lets integrators reliably purge the cache for the affected page(s).
  2. Optional built-in page-cache purge. When a comment for a page changes, remove that page's entry from kirby()->cache('pages') (driver-agnostic — works for file, APCu, Redis, and staticache alike). Could be gated behind an option such as mauricerenck.komments.flushPageCache => true.
  3. At minimum, document the caveat. Note in the SQLite-storage docs that DB storage no longer auto-invalidates page caches, and that integrators using a page cache must wire up invalidation via the hooks above.
Srijan Choudhary Srijan Choudhary

Knoppix nostalgia

Oh man, fond memories.
I remember being very interested in programming in middle/high school, but all the environments in our school computer lab had windows (this was in India), and I think at that time (maybe 2001-2003) I didn't even know there were other operating systems.
Our school was participating in something called International Cyber Olympiad, and of course I gave the eligibility exam.
They sent all students who passed a Knoppix Live CD to prepare for the actual competition. We did not have a PC at home until a couple of years later, but I used that CD in any PC I could find anywhere - the school computer lab, the school library computers, and my dad's office computers. It was my first experience with a Linux system (and I found it awesome). Also my first experience with gcc instead of borland c++.

Srijan Choudhary Srijan Choudhary

A small #Emacs #OrgMode quality-of-life tweak. I often need to replace an org heading's title while preserving the original text in the body. The problem is that pressing enter on a heading inserts a line above the properties drawer, which breaks things.

Here's a function that moves the heading title into the body (below the properties drawer and metadata), and binds it to S-RET:

(defun my-org-demote-title-to-body ()
  "Move the current heading's title into the body, below the metadata.
  Point returns to the heading for editing."
  (interactive)
  (org-back-to-heading t)
  (let* ((element (org-element-at-point))
         (title (org-element-property :raw-value element)))
    (org-edit-headline "")
    (save-excursion
      (org-end-of-meta-data t)
      (insert title "\n"))
    (org-beginning-of-line)))

(defun my-org-shift-return ()
  "On a heading, demote title to body. In a table, copy down."
  (interactive)
  (cond
   ((org-at-heading-p) (my-org-demote-title-to-body))
   ((org-at-table-p) (org-table-copy-down 1))
   (t (org-return))))
  (define-key org-mode-map (kbd "S-<return>") #'my-org-shift-return)
Srijan Choudhary Srijan Choudhary

Faced a failing disk in my raidz2 ZFS pool today.

Recovery was pretty simple:

  1. Asked the service provider to replace the disk
  2. Find new disk ID etc using:
    lsblk -o NAME,SIZE,MODEL,SERIAL,LABEL,FSTYPE
    ls -ltrh /dev/disk/by-id/ata-*
  3. Resilver using:
    sudo zpool replace lake <old_disk_id> <new_disk_id>
  4. Watch status using:
    watch zpool status -v

Re-silvering is still ongoing, but hopefully completes without issues. Will run a manual zpool scrub at the end to make sure everything is okay.