Ephes Blog

Miscellaneous things. Mostly Weeknotes and links I stumbled upon.

Date -

Weeknotes 2025-05-12

, Jochen
The thing about being wrong is that before you know you’re wrong, it feels •exactly• like being right. --Roman Mars

Beyond Tellerrand 2025

I attended the Beyond Tellerrand conference in Düsseldorf this year. Being local residents, my partner and I didn't have to travel far to the venue, and since we're both interested in the topics, we always attend together. In previous years, we'd bring our children along, taking turns watching them between talks. This year marked the first time both kids were in kindergarten or school in the mornings and at playdates in the afternoons, so they didn't join us. Several attendees actually noticed their absence and asked where we'd "left the little ones."

The conference was excellent as always. I gained plenty of inspiration and thoroughly enjoyed both the presentations and conversations with familiar faces and new acquaintances alike. I did find myself wondering if the conference might benefit from exploring even more diverse topics "beyond tellerrand." It would be fascinating to see someone like Simon Willison discuss AI and its implications, or perhaps dive into more technically in-depth backend topics that could bring fresh perspectives.

That said, I can't recommend Beyond Tellerrand highly enough! The event consistently delivers exceptional content in a welcoming atmosphere that encourages creativity and connection. If you haven't experienced it yet, you're truly missing out on one of the best web conferences in Europe. And if you can't make it yourself, definitely encourage a colleague or friend to go – they'll thank you for it!

Special shout-out to my fellow podcast colleagues who made this event even more enjoyable: Alexander Bürner (devslove.it), Christian Schaefer (Working Draft), Sarah Gross (wwsiv) – and to Daniel Pietzsch and Nik Rademacher – it was fantastic seeing all of you there!

Nyxmon

I've made significant progress with my experiment developing a minimalist monitoring tool using vibe coding. I now have a comprehensive integration test where I add a check to the database and launch a check collector in a separate thread. This collector uses a blocking portal to poll the database for checks that are due to run.

Once a check is identified, the system issues an "execute checks" command that leverages an async check runner adapter along with another blocking portal. This setup allows the pending checks to run via httpx async in the event loop before returning results back to the synchronous message bus through a callback.

After receiving the result, the system issues an "add result" command to the message bus. Then the SQLite repository adapter utilizes a portal to write the result to the database within an async context.

While the code structure appears somewhat complex, it seems to be functioning as intended. The architecture successfully bridges synchronous and asynchronous operations throughout the monitoring workflow.

django-cast

Just released a new version with official support for Wagtail 7 and Django 5.2.

Articles

Software

People


Weeknotes 2025-04-28

, Jochen
You can tell the Old Testament is the product of a desert people, because when they tried to imagine the end of the world they went with “rained for forty days and forty nights”, which in Ireland is just called Spring. --Simon McGarr

Attending DjangoConEU 2025

Last week I headed to DjangoCon Europe 2025 in Dublin, and it was fantastic. I met some wonderful people and had countless fascinating conversations. Since all the Python Podcast hosts were there with their audio gear, we pulled off the impressive feat of recording an episode every single day (day1, day2, day3) – and actually got them published within 24 hours of recording. We set up shop in the hotel lobby, initially worried about background noise, but Auphonic worked so well at filtering that I actually had to dial back the settings to keep some of the atmosphere in the recordings! I also got to watch another podcast being recorded at the conference, which was eye-opening. It was honestly surprising to see how differently various people approach the same task.

Dublin itself is a captivating city, and we managed to explore quite a bit. Here's something interesting: after chatting with other attendees, I discovered I'm not alone in finding software development work challenging right now (except for one person who never missed a chance to remind me they're probably the notable exception to the rule – you know who you are!). The tech market seems to be in a rough patch at the moment. At least I got some validation that it's not just me struggling.

Monitoring Pet Project

I haven't had time for much "vibe coding" on my monitoring pet project, but I've been thinking about the architecture, which is almost as good. Monitoring is essentially about waiting for I/O. You periodically poll the database to see which checks to run next, make HTTP requests (or other network calls) to actually perform those checks, and write the results back to the database.

The most straightforward way to handle I/O waiting in Python is using async functions and coroutines with an event loop. But here's the catch: you can only await async functions from within another async function. The problem is that most of my business logic – like deciding whether to run a check or determining if a failed check means a service should be marked as down – doesn't benefit from being async at all. In fact, it would be cleaner to keep the core domain logic synchronous and only use async for actual I/O operations.

So here's what I really want: a sync core for business logic that deals with the monitoring domain, with all the async I/O hidden behind adapters. But this raises a tricky question: how do you call async adapters from sync domain code?

There's another practical consideration: I'll likely want to build a Django dashboard at some point, and integrating synchronous business logic with Django is much more straightforward.

My plan involves using anyio for I/O since I want the flexibility to switch async backends later. Anyio has this neat concept called "portals" that let you run async code in another thread's event loop. Here's my current plan:

  1. Use dependency injection to provide a blocking portal to any event or command handlers that need it
  2. Keep all handlers synchronous, but allow them to pass the portal to adapters
  3. Let adapters run async code using the portal – either waiting for completion with portal.call() or fire-and-forget with portal.start_task_soon()
  4. When async adapters need to call business logic, they can do so directly (since calling sync business logic from async code should be fine)

This approach seems like a clean way to keep my domain logic simple while still leveraging async for I/O efficiency.

Articles

Software

Fediverse