毎年恒例,エイプリルフールのやつ ではありません.
2025年4月1日に 株式会社はてなに入社済みです.

今後とも
id:laminne をよろしくお願いします.
Cloudflare R2 - Pricing Calculator というのを見つけたので使ってみた

Promtail is now deprecated and will enter into Long-Term Support (LTS) beginning Feb. 13, 2025. This means that Promtail will no longer receive any new feature updates, but it will receive critical bug fixes and security fixes. Commercial support will end after the LTS phase, which we anticipate will extend for about 12 months until February 28, 2026. End-of-Life (EOL) phase for Promtail will begin once LTS ends. Promtail is expected to reach EOL on March 2, 2026, afterwards no future support or updates will be provided. All future feature development will occur in Grafana Alloy. If you are currently using Promtail, you should plan your migration to Alloy. The Alloy migration documentation includes a migration tool for converting your Promtail configuration to an Alloy configuration with a single command.

{ job = "journal"} | = "UFW" | logfmt みたいな感じで書く必要があって...
この記事は はてなエンジニア Advent Calendar 2025 16日目の記事です.
昨日は
id:Windymelt さんの HNSWのビジュアライザを作成したでした.
さて,表題の通り最近 Kotlin を書きはじめたので,この記事ではKotlinを書いてみた感想を書いてみようと思います.
私のバックグラウンドとしては TypeScript をメインにたまにGoやRubyを書くという感じで,いわゆるJVM系言語はほとんど触ったことがありませんでした. 書き始めるまでのKotlinの雑なイメージはこんな感じでした:
まずはじめに思ったのはクラスの種類が多いことでしょうか.
TypeScriptではclassだけですが,Kotlinにはdata class,sealed class,enum classなど様々種類のクラスが存在しています.まだ正しい使い分けが理解できていません...
それぞれの役割や特性としては:
data class: データ保持が目的.自動的にデータをコピーできるcopy()メソッドが実装される.
copy()メソッドはかなり便利で最初に見たときは感動した覚えがあります.sealed class: 継承できるクラスを同じパッケージ内に制限する.whenで網羅性チェックができる.enum class: 固定値を列挙できる.各値はインスタンスになる.when式が強いwhen式はswitch文より表現力が高く,分岐が結構簡潔に書けます.
TypeScriptやGoには無い機能なので,チュートリアルを走っている途中には結構強力な構文だなと思っていました
大分雑な例ですが,例えばプログラミングのテストで出てきそうな*1こんな感じのコードが
function formatScore(score: number): string { if (score >= 90) return "秀"; if (score >= 80) return "優"; if (score >= 70) return "良"; if (score >= 60) return "可"; return "不可"; }
Kotlinだとこう書けます:
fun formatScore(score: Int): String = when { score >= 90 -> "秀" score >= 80 -> "優" score >= 70 -> "良" score >= 60 -> "可" else -> "不可" }
関数呼び出しの時に引数名を指定できる機能です.
data class User( private val id: String, private val name: String, ) val user = User(id = "20251216", name = "laminne")
これがなかなか便利です. 引数が増えてくると順番を意識して書く必要がありますし,同じ型の引数を取り違えることも良く発生します. 同じような構文はRubyなどにもあります.
同じようなことをTypeScriptで書こうとすると,まずinterfaceやtypeを使ってオブジェクトの型を定義する必要があります:
interface UserArgs { id: string, name: string, } class User { private readonly id: string private readonly name: string constructor(args: UserArgs) { this.id = args.id this.name = args.name } } const user = new User({ id: "20251216", name: "laminne" })
TypeScriptのクラスにはコンストラクタでメンバ変数を定義できる構文があり,上のコードはこんな感じに書き直すことができます
class User { constructor( private readonly id: string, private readonly name: string, ) {} }
とはいえこの方法だとオブジェクトを使って受け取ることができないので,コンストラクタでメンバ変数に代入し直す必要があって辛い...
スコープ関数はラムダ式を使ってオブジェクトを操作するための関数*2です.
let,run,with,apply,alsoの5種類が存在していて,それぞれ少しずつ違う効果があります.使い分けるのが難しい....
例えばlet: ?.演算子と一緒に使うことが多い,nullableなオブジェクトに対して「中身がnullではない時だけ実行する」処理を書くときに使う.
val email: String? = user.getEmail() val trimmedEmail = email?.let { it.trim() } // 繋げて書くこともできる email ?.let { it.trim() } ?.let { it.lowercase() }
TypeScriptで同じことを書くと
const email: string | null = user.getEmail() const trimmedEmail = email !== null ? email.trim() : null
というようになります. if文や三項演算子で分岐させるのとメソッドチェーンのどっちが良いかは場合によると思っていますが,個人的にはメソッドチェーンできる方がわかりやすくて好きです.
最近書き始めたばかりで理解していないことの方が多い状態なので,あまり不満はありませんが,強いて言えば:
以上です.
*1:実際に学校のテストでこんな感じのコードをCで書いた覚えがあります
表題の通り,3/21に 独立行政法人国立高等専門学校機構 松江工業高等専門学校 情報工学科 を卒業しました.なんと!5年で卒業できてしまった...
私のソーシャルアカウントをフォローしている人はほとんどが高専について詳しいと(勝手に)思っているので高専本体の説明は最小限にしますが,高専はこういう学校です
スーパーダイジェストでお送りします.
共同開発鯖 (初期メンバー, 1年次) https://growthers.dev
Poporon Network (発起人, 2年次) https://poporon.org
25卒のプログラマーとして就職します.どこに就職するのかについては特に名言するつもりはありませんが,直接会う機会がある人には多分話すと思いますし.何かしらのカンファレンスに出たときに名刺交換するだろうからその時にわかるはず?です.
タイトルの通り、新しい分散/連合型SNSを開発している。
ソフトウェアの名前は"Pulsate"*1(パルセート と読む)で、プログラムは以下のrepositoryにある。
注意:
残念ながら後述する通りまだかなり荒削りな状態であり、プロダクション運用できる状態ではない。
この記事の内容は基本的に私の考えていることをダンプしたものであり、プロジェクトの公式見解ではないことに注意されたい。
Pulsateは
である。
Mastodon のような思想を持ち、misskey のような機能セットを提供し、それでいてどのソフトウェアとも関係のない独立した実装だ。
機能の名前は基本的にmisskeyと同じ*2。
投稿: ノート
再投稿: リノート
引用再投稿: 引用リノート
技術スタックとしては:
を採用している。
このプロジェクトでは新しい技術を取り入れつつ他の部分では多少枯れた技術も採用していくつもりだ。
1/17 補足:
PulsateではバックエンドでもTypeScriptを採用している。理由は:
というような感じです。開発開始後も何回か言語を変更するか?といった検討がなされたことがありましたが、すでに書かれているコードを放棄するよりは継続開発した方が良いだろうといった結論になり、結局TypeScriptを採用し続けているというわけです。
補足終わり
フロントエンドは?となるかもしれないが、Pulsate は標準のフロントエンドを同梱しない。Pulsate 向けのフロントエンドは同じ団体(Pulsate Project)が開発する別ソフトウェア扱い*3で、Caramel (カラメル)という別の名前が付いている。
現在時点でのCaramelの技術スタックは:
という感じになっている。Remixの雲行きが怪しくなってきているので別のスタックに切り替えることを検討している。
Caramelは"とりあえず使い物になる"レベルの実装しかしていない最小かつ最軽量なフロントエンドであるため、恐ろしくシンプルで消極的なUIである。



ほとんどCSSは書かれいていないし、リアクションは👍の1種類しかつけることができず誰がつけたのかも知ることができない。あとはフォローもできない。
ただ単に(フロントエンド側が)未実装なのもあるが、バックエンドで実装される全ての機能に対応するつもりがないのは事実だ。
もし"なんだこのけしからんフロントエンドは!"と思う人がこの記事を読む人の中にいるなら、この記事を一番下まで読んでぜひ私たちと一緒にこのけしからんソフトウェアを改善して、Fediverseの世界をもっと良くしよう。
Pulsate関連ソフトウェアのライセンスはApache2.0で、他ソフトウェアで広く採用されているAGPLは採用していない。
理由としてはAGPLは 厳格なコピーレフト型ライセンス であり、フォークの開発者にかかる手間が多いためライセンス違反が発生する可能性がほかと比べて高く、それに対する対処などが複雑になると考えたから と、単に開発開始時にApache2.0ライセンスが一番合っているだろうと判断したからだ。
(注: この類のSNSは一般的には"分散型SNS"と表記することが圧倒的に多いが、この記事では後述する理由によってあえてこう表記する)
公式サイトに書いてあるプロジェクトが目指すものはこんな感じだ:
Pulsateの開発開始時に"最も解決したいこと"であったものの一つ。
他実装では"大量のユーザーの投稿や操作をどうさばくか"が重要視されるのに対し、Pulsateでは"そこまで多くない投稿や操作をいかに効率よく処理するか"を重要視していくつもりだ。
分散/連合型SNSの統計をとっている FediIndex (https://fedi.wrm.sr/) によると、ユーザー数100人以下のインスタンスが93.23%と大半を占めている。

ほとんどのインスタンスは非常に小規模であるので、何千何万というレベルの同時接続に耐えることが可能な大掛かりな仕組みよりも運営にかかるコストを削減したり、維持に必要な操作を自動で行ったりできる仕組みを導入したほうが効果があると考えている。
Pulsateは中小規模(〜1000人)のインスタンスをメインタゲートに絞って開発していく予定だ。
分散/連合型のSNSをあまり使ったことがない人にとって、リモート/ローカルの概念やフォローの方法を理解するのは相当に難しいことだと思う。
Pulsateは技術者や分散/連合型SNSを使ってきたユーザーだけではなく、標準的なSNSのユーザーやあまり短文投稿系のSNSに触れてこなかったユーザーもターゲットにしたいと考えている。
そのために、シンプルかつ直観的に使いやすい(フロントエンドの)デザインであるとか、極力難しい単語(技術用語)を排除するなどの対応を行っていくつもりだ。
PulsateではDiscordに開発者同士、ユーザー同士がコミュニケーションできるようなコミュニティーサーバーを設けている。もちろん開発に関連する(ほぼ)全ての会話はここでオープンな形で行われている。
コミュニティーサーバーは以下からアクセスできる。
Pulsateの開発チームにはオープンソースであるのなら開発方針や開発の様子は基本的にオープンにしていくべきという考えがあり、それの一環としてこのようなコミュニティーを設けている。
こうすることで、
といったメリットがあると考えている。
また、内部のアーキテクチャ/設計ドキュメントなどのPulsate自体の開発ドキュメントを完全にオープンにする。具体的にどのようなドキュメントを書き、どのように活用するかは決まっていないが、外部コントリビューターの確保やプログラムの維持管理に活かせると考えている。
かなり荒削りで不完全ではあるが*4、すでに一部のモデルの仕様が公開されている。
さらに、様々なプログラミング言語向けのAPIクライアントライブラリを公式提供する予定だ。Pulsateは他のSNSとAPIの互換性がないため、Botやアプリの開発を行うためにはAPIクライアントを自作する必要が出てきてしまう。
他のSNSではそういった場合でも公式でライブラリが提供される事例はほぼ無いが、Pulsateではいくらかの需要の大きいプログラミング言語向けのライブラリを公式で提供する予定だ。
すでにAPIドキュメントと全てのエンドポイントの型はOpenAPI Spec(OpenAIではない)方式でコードから自動生成されているので、公式提供されないプログラミング言語向けのライブラリも手書きすることなく自動で生成できる。
この記事では"分散型SNS"という表記をせず"分散/連合型SNS"と表記しているが、これには理由がある。
個人的に分散 と 連合 は指す意味が違うと考えているからだ。
おおむねこんな感じに理解している:
分散: 大きいSNS(インスタンスのこともある)を複数に分け、ユーザーを散らす
連合: 複数の(種類の違うこともある)独立したSNSを繋いで1つにする
"分散型SNS"と表記すると単にユーザーやインスタンスがバラバラになる印象が大きくなると考えていて、そのために"連合型"という 複数のものがつながる という意味の言葉を採用している。
Pulsateのプロジェクト全体の標語(キャッチコピー)は「繋がりを"再定義する"」だが、ここで言うところの 繋がり にはユーザー同士の関係だけでなくインスタンス/サービス/ソフトウェア同士のつながりも含まれている。
Pulsateは歴史的経緯*5からActivityPubに関連した処理をSNSの基本機能(ログインや投稿、フォローなど)から完全に独立させる形で設計している。
アプローチはmisskeyのそれとほとんど同じで、先に最低限独立したSNSとして使えるようにしてからActivityPubに関連する機能を実装していく という形式を取っている。
とはいっても、連合に対する考え方はmisskeyとほぼ真逆である。
misskeyは「あくまで連合(分散)は従」であり、基本機能を最優先として連合に対して消極的である*6*7。
一方Pulsateは「連合は重要な概念であり、既存のSNSとの互換性を保ちどのインスタンスにいてもシームレスに繋がり続けることができること」を重要視する。
このようなスタンスを"連合志向"と言う。Pulsateは連合志向な独立実装である。
具体的には:
前述した通りPulsateはApache2.0ライセンスで配布されている。コードがオープンでも開発がオープンでないこともあるが、Pulsateの開発はオープンに行われている。
独立性に関してはPulsateの開発チーム(pulsate-dev)とPulsateに関連する全てを管理するPulsate Projectは完全に非営利かつ独立であり続ける。(Pulsateを利用した)巨大インスタンスの運営団体や法人の傘下に入ることはないし、そうした組織から意思決定に干渉されることもない。意思決定に重要なのはあくまでユーザー本位、分散/連合型SNSとしてどうあるべきかということだけだ。
コントリビューターや利用者の数が増え、プロジェクト規模が大きくなった際には透明性の高いガバナンスの導入を計画している。私が今考えている主な取り組みは以下の通り:
簡単なレポートの形で数ヶ月おきに最近の進捗などを公開するところから初めていくつもりだ。
現在時点で考えている目標はこのような感じにしている。
あまり具体的ではないし、目標も高いのか低いのかよくわからないが、とりあえず私個人としてはこれくらいの目標でいこうと思っている。
現状、Pulsate Projectは他のプロジェクトに比べてかなり小規模だ。アクティブに活動しているプログラマーは実質私1人で、PulsateもCaramelもどちらも私が書いている。
もう1人アーキテクト/レビュワー兼プロダクトオーナー(最終的意思決定者)がいるが、やはり開発者の人手が足りない。
注: 現在私ともう一人の開発者は卒業研究が佳境に入っており、(私は)2月中旬ごろまでそこまでプログラムをかけない状態になっている。
基本機能(ノート、リノート、リスト、フォロー、タイムライン)についてはPulsateで実装済みではあるものの、その大部分がCaramelで利用できない状態だ。
そんな状態ではあるが、プログラム自体は腐らずに保たれている。
misskeyのコードについてコントリビューターが嘆いていたのを見ていたのでかなり丁寧にソフトウェア設計を行っており、単体テストもほぼ全てのロジックについて書かれている*9。
ActivityPub関連の実装はまだほとんど行われていないが、既存の処理を適切に呼び出せば実装はできる状態にはなっている。
また、JSON-LD(ActivityPubのサーバー間通信で使われるJSONに似たフォーマット)からJSONとの相互変換や、かなり実装が難しいとされるリクエストの署名の処理周りは、最近ActivityPub実装自作の世界で注目を集めている Fedify を利用するつもりだ。
もともとはDeno向けに書かれたようだが、Web標準APIを利用しているためPulsateが使っているNodeでも利用可能なので非常に助かる。
こうした便利なライブラリを利用することで開発にかかる手間を減らすことができ、結果的にユーザーに価値を提供し続けることのできる力を生み出すことができるのではないかと考える。
さて、見出しの通りPulsate/Caramelの開発に参加しませんか。
(開発以外にもアイデアを提供したり、コミュニティーサーバーで発言したりするなどの貢献方法がある。)
プロジェクトや開発に興味があるという方はコミュニティーサーバーにぜひ。
ソースコードを読んで全体の様子を見てみたいという場合は GH: pulsate-dev/pulsate にコードがある。
あまり発言はないがFediverseにもアカウントがある。
TwitterかFediverseで #pulsate をつけて投稿していただければ(筆者が)何かしら反応する。
(Fediverseの方はnotestockをお使いならばすぐ反応できると思う)
ActivityPubに関連したアプリケーションを書いてみたい人、
つくりたいものが特にないがWebアプリ開発がしたい学生(今まで開発に関わった人は全員学生)、
"misskey 連合 つらい うんざりザリガニ" *10 という感じの人は Pulsate Project にぴったりな人*11だと勝手に思う。
以上だ。
Fediverseの世界がより良いものになることを願って。
*1:Indigo la end のアルバムの名前に由来するらしい
*2:ActivityPub上での投稿のオブジェクト名もNoteなのでそちらに影響を受けているとも言える
*3:公式クライアントを使わないという選択肢も尊重するため
*4:いまあるドキュメントをどのように維持していくかが喫緊の課題になりつつある。
*5:開発開始した2023年9月頃はBlueskyなどのActivityPub以外のプロトコル実装が乱立しており、ActivityPub以外のプロトコル実装も行う必要性が0ではなかった
*6:開発者が「連合はおまけ」と発言し物議を醸したことがある
*7:この数ヶ月最大インスタンスの運用者が資金など様々な理由から連合の終了を示唆して批判されている
*8:ソース: https://misskey.io/@syuilo/pages/ltl
*9:バリデーション用の型定義などのテストを書けない部分を含めた全プログラムに対するカバレッジ: 49.54%
*10:元ネタ: https://blog.3qe.us/entry/2024/04/19/200735
*11:Pulsateはmisskeyの連合関連の不満やソフトウェアに対する考え方に異を唱える会話の中で生まれた
2025年の抱負。遅すぎるというのはそうかも。
記事というよりメモになりそう。
終わり 適当に更新するかも