I'm blogging about Emacs, Drupal, php and exciting subjects

· Lars Nielsen

Why I Didn't Use Symfony Messenger for a Shared Crawl Queue

In July my search engine needed a queue that several servers could share: crawlers on one machine putting fetched pages in, indexers on others taking them out. The project already depended on Symfony Messenger, and a Messenger transport DSN pointing at the database was even configured on one of the servers. Reusing it looked like the obvious move.

Read article Why I Didn't Use Symfony Messenger for a Shared Crawl Queue
· Lars Nielsen

Fact-Checking AI-Drafted Technical Articles: The Numbers Were Right, the Explanations Weren't

Articles on this site are drafted with an AI agent, Claude, working from my git history and design notes, and every draft goes through a verification pass before it's scheduled. On 15 October, an unattended pipeline run drafted and scheduled seven articles. I then checked them against the commits they were based on, and six of the seven contained a factual error.

Read article Fact-Checking AI-Drafted Technical Articles: The Numbers Were Right, the Explanations Weren't
· Lars Nielsen

Keyset Pagination Fixed a PHP Out-of-Memory Crash Loop That Docker Never Saw

In August, two background workers in my search engine had been crashing with PHP out-of-memory errors for about 20 hours before anyone noticed. Nothing looked wrong from the outside: docker ps showed the containers up, with a restart count of zero. What gave it away was that the whole fleet looked unusually loaded.

Read article Keyset Pagination Fixed a PHP Out-of-Memory Crash Loop That Docker Never Saw
· Lars Nielsen

One Big Query or Many Small Ones? Batching Halved My Queries per Page and the Load Didn't Move

"Is one big query faster than many small ones?" is one of the most-viewed database questions there is, and the usual answer is "batch it". In July I batched the writes of my search engine's indexer, which cut the number of MySQL queries per indexed page roughly in half.

Read article One Big Query or Many Small Ones? Batching Halved My Queries per Page and the Load Didn't Move
· Lars Nielsen

Article JSON-LD on a Drupal Site: publisher and mainEntityOfPage Aren't What Google Asks For

Until September, this site had no structured data at all: no JSON-LD, no microdata, not even Open Graph tags. I noticed because the search-appearance report in Search Console came back completely empty in two exports in a row. I added Open Graph tags and a block of JSON-LD to every article page, including publisher and mainEntityOfPage.

Read article Article JSON-LD on a Drupal Site: publisher and mainEntityOfPage Aren't What Google Asks For
· Lars Nielsen

Python requests Doesn't Trust mkcert's CA Off Debian: certifi and a Per-Run CA Bundle

The script that publishes articles on this site tests every article on a local copy of the site first, at https://linkhub.ddev.site. That local site runs in DDEV, and its HTTPS certificate is signed by a local certificate authority that mkcert created. On the Ubuntu install where the pipeline started, that just worked.

Read article Python requests Doesn't Trust mkcert's CA Off Debian: certifi and a Per-Run CA Bundle
· Lars Nielsen

An SSH Deploy Key for CI That Can Only Run Two Commands: authorized_keys command= and SSH_ORIGINAL_COMMAND

CaRMen's deploys start in GitHub Actions and end on a server, and something has to cross that gap. Here it's an SSH key, stored as a secret in the repository, that the deploy job uses to connect to the server and run the deploy. A key like that is exactly the kind of secret that leaks: it sits in a CI system, it's used automatically, and nobody watches each use. So the key can't open a shell.

Read article An SSH Deploy Key for CI That Can Only Run Two Commands: authorized_keys command= and SSH_ORIGINAL_COMMAND
Subscribe to Linkhub