Tag: code

Redis sorted sets are cool

I first saw Redis sorted sets in action reading Mastodon’s source code. Sorted sets are used to store feeds (ignore that ZREVRANGEBYSCORE is deprecated). In a use-case such as Mastodon feeds (timelines), sorted sets come handy because you can “just” add new elements and Redis will take care of the sorting.

variety of fruits displayed on wooden shelf

Server-side rendering a ClojureScript app with Deno

タイトルは英語のままなのは、日本語にしようとしても結局全部カタカナになるので放置。さてre-frameは俺的にClojureScriptでウェブのフロントエンド作るにあたって標準装備になっているが、ものによっては完全動的に生成されるReactのアプリよりも、検索エンジンなどでも絶対拾える静的HTMLを返した方がいいという場合もある。今回は流行り言葉をいっぱい使えるように、Denoを活かしてClojureScriptアプリのサーバーサイドレンダリングを実現しようと思います。動くコードはGithubにて


Frontend/backend shared routing with reitit

Commonly frontend and backend are separate beasts. Backend written in Ruby using Rails for example, its routing written in its own DSL. Frontend written in TypeScript using Vue.js for example, its routing written in its own DSL. Of course the frontend will call some backend endpoints, so it should definitely know about those backend endpoints too, while there may be some frontend “paths” that don’t correspond to any single API endpoint, yet you might want to generate absolute URLs for those pages on the backend. This results in a nasty mess and duplication of routing and adjacent logic.

asphalt road between trees

Elasticsearch aggregation to find most popular tags over time

Finding popular keywords or tags is what twitter’s trends are (other than a means to manipulate public opinion and introduce artificial trends by paying good cash). While I think having a “trends” feature tends to introduce more problems than the value it provides for discovery, I wanted to figure out how I’d do it before deciding not to.


Dealing with circular dependencies in Clojure

While working on stuff (of course in Clojure), I kept running into problems with namespaces having circular dependencies. For example I’d have an app.router namespace that defines the, uh, routes. I’d have an app.url namespace that contains helper functions to generate absolute URLs based on route data (so it depends on app.router). I’d have an app.views namespace that uses those URL helpers (thus depending on app.url), and these views would be referenced in the routes so app.router would require app.views.

This completes the dependency circle and is the beginning of my journey. There are a bunch of ways to deal with circular dependencies in Clojure, but I won’t go in-depth about all of them.

timelapse photography of fire

Adding Grafana annotations based on Flux CD events

Earlier this year I wrote about adding Grafana annotations based on Argo CD events. Since this year I actually got around testing out Flux some more, it was natural to follow up with adding some Grafana annotations based on Flux events.


ClojureDartの第一印象

Clojureの文法でFlutterが書けると聞いた時、これだ!と思った。ClojureDartはただClojureの文法をDartに変換するツールよりも、Flutterがメインだと感じた(個人的にDartもそうだと思っている)。ClojureDartはすごく短時間で「やるぞ」の発表から実際にだれでも試せるような形に発展した。あとからコミットログ見返すと、もっと前から作っていたらしいけど。

最近モバイルアプリ手掛けることになって、プロトタイプ作るにClojureDart試すことにした。困ったことはいろいろとあったが、後悔はしていない。

black and brown dart board

Clojure multimethods and derivation

I’ve known about Clojure multimethods of course, but I never really used them much. I didn’t really have data that I’d need polymorphism like multimethods to handle, and when I did need something like that I’d use protocols. However protocols dispatch based on class, so when I faced the problem of handling ActivityPub objects that are all maps, it was time for defmulti to save the day.

red yellow and green abstract painting

Structured logging in Clojure

The first time I ran into “structured logging” was way, way back when I first started working on kitsune. Back then I went with the approach of using a Logback Formatter (the JacksonJsonFormatter) to log Clojure maps as JSON. This was nice because I didn’t have to do anything to “transform” the logs further, but had the quite significant downside that logs weren’t really human readable anymore. This plus that that log processors like Loki and CloudWatch can easily parse huge amounts of “traditional” text logs made me pretty much forget about structured logging until recently.

That is until in a thread on the clojurians slack about logging someone mentioned mulog, a structured logging library that caught my attention. I guess maybe from a traditional Clojure background it would’ve been natural to end up with taoensso/timbre at this point, but I never did that bit (though I do have it as an indirect dependency).


The Weave GitOps UI for Flux

Unlike Argo, Flux has no built-in UI. CD tools should be invisible most of the time, just quietly running in the back, getting changes in the cluster. This is fine for “most of the time” when there are no changes to the applications I’m making myself or the cluster itself. It can just look at the various helm charts and other (git) sources and deploying the changes as configured. It’s nice that I can be sure that my cluster has the latest possible versions of everything running within 10-15 minutes of release (depending on the Flux interval configured) without ever touching kubectl.