Mastodonの鯖缶を4年ほどやってみての雑感

はじめに

この記事はFediverse Advent Calendar 2021 の7日目の記事です。

adventar.org

 

2017年からMastodonサーバーを運営してみての雑感を書きたいと思い、参加しました。

 

軽く自己紹介

S.H.という名前で、Creatodonという創作系のMastodonサーバーの管理人をしています。

gamelinks007.net

 

また、Mastodonのバックエンドで使用されているプログラミング言語Rubyに趣味でパッチなどを投げてたりします。

 

その辺の話は以下の記事にまとまっていますので、そちらを読んでいただければと思います。

gamelinks007.hatenablog.com

 

4年間の振り返りなど

運営など

2017年4月のMastodonブーム以来、色んなサーバーが出来ては消えていきました。

DBが爆破しちゃったり、アップデートが上手くいかなかったり、運営に疲れたり、その理由は様々でした。

 

うちのサーバーは時々トラブルが起きたものの、幸いDBの爆破などもなく平穏でした。

またユーザーも各々が好きなことをしている感じなので大きなトラブルとかもなく(まあ、僕の観測範囲内に無いだけかもですが)緩い感じで運営できていました。

 

そのおかげか鯖缶として運営に疲れるとかそういうこともなかったですね。

 

ほかのサーバーもそうなのかはわかりませんが、あんまり気張って運営していないくらいが気楽で運営しやすいのかもしれません。

僕の観測範囲ですが、古くからあるサーバーはガチガチの運営でもなかったりするように思いますし

 

そのほかの分散SNSなど

この四年間でPleromaやMisskey、今は亡きHivewayなど様々な分散SNSが登場し、ずいぶんとFediverseは賑やかになってきたなぁと思います(2017年のころだとGNU ScoialとかMastodonとかくらい?だったと思うので)

 

その分サーバーの数も増え、人の交流も増えたと思います。

 

ただ、同時に何かしらのトラブルを見かけることも増えたように思います。

 

そのトラブルも分散SNSの仕組みのおかげか関連する投稿が流れてくることも少ないですし、ドメインブロックなどで元から断つこともできたりするので大丈夫かなと思ってたり。

 

まあ、一人のユーザーとしても、SNSを運営する管理人としても複数の選択肢が出てきたのはうれしいですね。

 

個人としての分散SNS

一個人として分散SNSを使う分にはかなり満足していますね。

特に自分の好きなように呟けるサーバーを自分で運営しているというのは大きいかなと。

 

それといくつものサーバーがあり、サーバーそれぞれのカラーも違うので自分に合っているところを探してもいいですし、または自分で建ててもよいところも好きですね。

 

いい意味で好きにできる土壌はあるなと思ってます。

 

ただ、その分自分と価値観の違う人と出会うことも多いので、衝撃を受けることもあったりします。

それがいい刺激の時もあれば、良くないときもあります。

 

そういう時にスッと距離を置きやすいのは分散SNSのいいところかなと思いますね。

 

おわりに

 

Mastodonサーバーを建ててからもう4年も経っているのかと思うと感慨深いですね……。

今後も緩く運営していきたいと思います。

rstdという趣味ライブラリを作っています

はじめに

この記事は Ruby Advent Calendar2 2021の12/6の記事です。

qiita.com

二年くらい前から趣味で作っているrstdというライブラリの紹介したいと思い、参加しました。

作っているもの

rtsdという「標準ライブラリにあると便利そうなメソッド」をRefinementsを使って実装しているライブラリを作っています。

github.com

きっかけ

Array#both_endというメソッドをbugs.ruby-langで提案したのが切っ掛けで作り始めました。

bugs.ruby-lang.org

挙動としては以下のような感じで動くと良いのではと考えてました。

# 通常のArray
ary = [ "w", "x", "y", "z" ]
ary.both_end     #=> ["w", "z"]
ary.both_end(2)  #=> [["w", "x"], ["y", "z"]

# 空のArray
[].both_end    #=> [nil, nil]
[].both_end    #=> [nil, nil]

提案したところコミッターの卜部さんから「Why not start as a gem? There are things not possible without core changes, but it seems this requested feature needs no such things.」とコメントがあり、gemで実装もできるしやってみるかとなりrtsdを作り始めました。

モチベーションなど

基本的に気の向いたときに実装をしたり、CIのメンテナンスしたりとかな感じです。 なので、一時コミットが全くなかったり……。

最近は少しずつ暇を見つけてはアレコレ便利そうなメソッドを追加したりしてます。

最終的にどういうものにしたいとか明確な目標はないですが、少なくとも「自分が使ってて便利そうなメソッドを追加する」という方針だけは維持してゆるく作りたいと思ってます。

使い方

rtsdは以下のようにrequireした後に、使用したいメソッドを定義しているModuleusingするだけです。

require "rstd"

using Rstd::RefineInteger

41.inc
# => 42

個人的に気に入っているメソッドなど

Array#has?

Array#has?は以下のような配列内に引数で渡した値があるかをチェックしてくれるメソッドです。 既に標準ライブラリではArray#include?がありますが、もう少し短く書きたかったので追加した感じです。

require 'rtsd'

using Rstd::RefineArray

ary = [1, 2, 3, 4, 5]

ary.has?(1)
# => true

ary.has?(117)
# => false

Hash#has_pair?

Hash#has_pair?は特定のキーとバリューの組み合わせを持っているかをチェックするメソッドですね。 Hash#has_key?Hash#has_value?を組み合わせて書いても良いんですが、毎回書くのも面倒だなと思い、追加しています。

require 'rstd'

using Rstd::RefineHash

hash = {jhon: 'S-117', linda: 'S-058', fred: 'S-104', kelly: 'S-104'}

hash.has_pair?(:jhon, 'S-117')
# => true

has.has_pair?(:daisy, 'S-023')
# => false

Kernel.#refine_method

Kernel.#refine_methodはクラス内でブロックとRefinementsを使って、良い感じにその場でメソッドを追加したいので実装してみました。

require 'rstd'

using Rstd::RefineKernel

using refine_method(Integer, :halo) do
  p 'Master Chief is came back!'
end

42.halo
# => 'Master Chief is came back!'

こんな感じで書けるので個人的には一番良く使っています。

おわりに

簡単ですが、趣味で作っているライブラリを紹介させていただきました。 今後、色々便利メソッドとか実装してみて標準にもあると嬉しいなというものがあれば提案していきたいと思います。

島根県浜田市での暮らしなど

はじめに

この記事は地方在住 Advent Calendar 2021の12/5の記事です。

僕も地方在住でリモートで仕事をしているので日々の生活などを振り返ってみようかと思い参加しました。

 

居住地

現在は島根県浜田市に住んでいます。もともと出身も島根県西部のほうなので生まれてこの方島根から出たことがないのが自慢です。

 

浜田市に住むきっかけは市内にある大学に進学して、そのままそこの地元企業に就職したためですね。

で、以下の記事でも触れていますが、社会人になってから本格的にプログラミング学んで現職に転職してます

 

gamelinks007.hatenablog.com

 

 

仕事など

リモートで東京のメンバーと一緒に仕事しています。

現在はCRE(Customer Reliability Engineering: 顧客信頼性エンジニアリング)というロールで顧客満足度改善のための改修などをメインにGoやTypeScript(React)で開発をしています。

 

あとは島根県浜田市の地域.rbであるHamada.rbを主催してたり、浜田市若者会議という市への提言をするグループとかに参加してITを使った街づくりとか提案したりしてます。

 

gamelinks007.hatenablog.com

 

 

gamelinks007.hatenablog.com

 

日々の暮らしなど

島根県浜田市特定第3種漁港もあるので、新鮮な魚を普段から安く買えるのがうれしいですね。たまにスーパーとかで丸ごと一尾買って自分で捌いたりもしてます。

 

特に市としても売り出しているどんちっち三魚(アジ、ノドグロ、カレイ)は非常に美味です。

 

個人的にオススメなのは「めし処ぐっさん」というところが提供しているノドグロの炙り丼です。

 

f:id:gamelinks007:20211204232244p:plain



脂たっぷりで非常に美味しいので浜田市に来られる際にはぜひ試してみてください。

 

 

www.kankou-hamada.org

 

あと、浜田市は日本酒の酒蔵もあり、美味しい海鮮と合わせて日本酒も楽しめるのでお酒好きの方にもおすすめです。

 

shimane-sake.or.jp

 

あと島根自体は酒蔵も多く、天隠とか七冠馬とか玉鋼など美味しい日本酒も多いので最近はその辺を晩酌で楽しんでたりします。

 

それと新型コロナウイルスの影響で行けていませんが、温泉街もあるのでそこへたまに疲れをいやしに行ってたりもしました。

 

www.kankou-hamada.org

 

PCで長時間コード書いたりしてると肩こりとかも酷くなるので、温泉に気軽に行けるのは助かってました。

最近行けてないので、どこかのタイミングで行きたいなぁ……。

 

おわりに

とりあえず、雑に書いてますが現状浜田市での生活に大きな不満はないですね。

美味しいご飯と日本酒とか楽しめてて、温泉とかもあるのでだいぶ楽しく生活してます。

 

少しだけ難点があるとすると映画館で映画を見るのに広島か出雲まで行かないといけないのは辛いですね……。

そこらへんが解消されたら嬉しいですが、どうだろうなぁ……。

近況報告という名の振り返り

はじめに

この記事はRubyist近況 Advent Calendar2021(2スレ目)の12/3の記事です。

近況報告の体で今年一年を振り返ってみようかなと思い、参加してみました。

 

この一年でやってたこと

お仕事

 

お仕事のほうではCREというポジションに就き、Go/TypeScriptを使い自社サービスの改善などをガンガン進めることになりました。

 

ちなみにCREについては以下の記事が詳しいです。

engineering.mercari.com

 

で、お仕事として以下のようなことをやってたりしました。

 

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

 

基本的にGo/TypeScriptばかりですが、Zoomの動画を文字起こしするのだけは個人的な趣味でRubyを使ってたりします。

 

あと最近はリリースの対応とかを率先してやるようにしていて、改善のサイクルをガンガン回せるように気を付けてたりします。

 

浜田市での活動とか

現在、島根県浜田市に住みつつリモートで仕事をしています。

で、隙間時間とかを使って高校生にプログラマーの仕事について話したり、便利そうなLINE botとかを作ってたりしてます。

 

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

gamelinks007.hatenablog.com

 

CRubyへのPRとか

去年もCRubyに色々PR投げたりしてたんですが、今年はよりアレコレ投げてた感じですね。

コミットなどは以下にまとまってます。

 

github.com

 

個人的には以下の「RubyRuby自体を実装してパフォーマンスが向上した」系のPRがマージされたのがうれしいですね。

 

github.com

github.com

github.com

 

来年もゆるく頑張っていきたいと思います。

Hamada.rb

Hamada.rbという地域.rbのオーガナイザーもやってまして、今年で無事丸二年たちました。

hamadarb.connpass.com

 

ちなみに今確認したらRuby Hacking Challenge in Hamada.rbもはじめてから丸二年たってたみたいです。

こちらはCRubyの内部実装読んだり、最近出たチケットの話とかをしてます。

 

元々はクックパッドで開催されていたRuby Hack Challenge の資料とか使わせてもらいつつ、開催してました。

rhc.connpass.com

 

ある時から、CRubyの実装を読んだりしてる人が集まる感じになってきたのでCRubyの実装を読んだりする感じにシフトしていった感じですね。

ちなみに、今年Rubyに投げたPRとかもこのイベントの時に作ってたりしました。

 

今後の目標としては浜田Ruby会議とかやりたいなと思ってます。

 

おわりに

近況報告という体で一年振り返ってみたんですが、まあアレコレやってたなという印象。

来年も引き続きやっていきたいですね。

浜田市への意見などを投稿できる目安箱サービスを試しに作ってみた

はじめに

元々は浜田市若者会議という会で、「浜田市に住んでいる若者がどんな意見を持っているかを知りたい」という話が出たのがきっかけです。 とりあえず、作ってはみたんですがまだ実際にリリースしたりするように話が詰まっていないので、本当にリリースするかは未定です。

ちなみに、浜田市若者会議についてはこちらの記事を参照していただければと思います。

gamelinks007.hatenablog.com

で、色々とアイディアとか仕様とかまとめたところを「目安箱のようなサービスでいいんじゃないか?」と思い、この土日を使って実際に作ってみました。

作ったもの

github.com

f:id:gamelinks007:20211115222921p:plain

Firebase/React/TypeScriptを使い、開発しました。

投稿されたご意見はFirebaseのRealtime DBに保存され、保存されるタイミングでCloud Functionsに追加した処理が呼び出され、Slackに自動で転送されるようになっています。

やったこと

基本的にはコミットログを見ていただければわかりますが、Firebase周りの設定を整えたりBlumaを使っていい感じにコンポーネントを作ったりしています。 あと、フォーム周りは react-bulma-componentsbulma-toastを使ってシンプルに実装しています。

なので、全体的にあまり時間はかかってない感じですね。

あとは、Slackへの転送する処理とかを以下のような感じで実装してます。

github.com

ちなみに、問い合わせなども同じようにSlackに流すようにしています。

おわりに

とりあえず、サクッとFirebaseを使ってシンプルな目安箱サービスを作れた! あとは実際にサービスとして提供できるように諸々の話を詰めていきたいですね

GoでWebsocketを使ったリアルタイムチャットを作ってみた

はじめに

勉強がてらGoでWebsocketを使ったチャットアプリを作ってみた時の備忘録です。

作ったもの

github.com

フレームワークとしてはGinを使い、ORMにはgorm v2を使っています。 またWebsocket周りはmelodyを使っています。

github.com

やったこと

細かいところは基本的にはコミットログをにまとまっているのでそちらを見ていただければと思います。

github.com

実装の肝としては、routes/setup.goに以下のようにWebsocket用のルーティングを追加して、

   // チャットルーム用のWebsocket接続先
    router.GET("/rooms/:id/messages/ws", messageController.Websocket)

    m.HandleMessage(func(s *melody.Session, msg []byte) {
        m.Broadcast(msg)
    })

    m.HandleConnect(func(s *melody.Session) {
        log.Printf("websocket connection open. [session: %#v]\n", s)
    })

    m.HandleDisconnect(func(s *melody.Session) {
        log.Printf("websocket connection close. [session: %#v]\n", s)
    })

    // メッセージがブロードキャストされたときの処理
    m.HandleMessage(messageController.Broadcast)

フロント側から接続するときのルーティングとWebsocket周りの接続を設定しています。

あとは、メッセージを作成する処理をコントローラーのアクションを以下のように作成しています。

func (messageController *messageController) Broadcast(s *melody.Session, msg []byte) {

    roomPath := strings.Trim(s.Request.URL.Path, "/roomsmessagews")
    roomID, _ := strconv.ParseUint(roomPath, 10, 64)
    var message model.Message
    message.Content = fmt.Sprintf("%s", msg)
    message.RoomID = roomID
    messageController.messageRepository.Store(messageController.db, &message)

    messageController.m.BroadcastFilter(msg, func(q *melody.Session) bool {
        return q.Request.URL.Path == s.Request.URL.Path
    })
}

あとはフロント側でWebsocketのエンドポイントに接続させておけばいい感じです。

やってみて

意外と簡単に実装できたので今後仕事のコードとかで導入してみてもいいかなと思いました。

gormでPreload周りのメモリ使用量とかを比較してみた

はじめに

gamelinks007.hatenablog.com

この記事は、上記の記事でgormのバージョンを上げる際にPreload周りの挙動を調べてた時のあれこれをまとめたものです。

ことの発端

gorm v2へのアップデート時に、一部処理でメモリリークらしき挙動が確認されたのがことの発端。 で、色々調べてた感じでgorm v2でPrelaod関連でmap[string]interface{}がそこそこ使われてたのでこの辺でメモリリークしてるのかもと思いPreload周りのメモリ使用量を調査してみました。

ちなみに、メモリリークしてたのは変なクエリをコード内で作成してて、それが原因でテーブル内のレコードを全件取得してたのが原因でした……。

前提条件

gorm v1とv2との間でPreloadを多用した際にメモリの使用量に差が出るのかを調査します。

メモリ使用量などはPrometheusやGrafanaを使いグラフで監視することにしました。

また最低限度の実装でも再現するのかを確認したいので使用するライブラリは以下のものだけにしています。

  • gin
  • gorm(v1またはv2)
  • sqlite3

またベンチマークにはApache Benchを使用し、ベンチマーク用のプログラムとしては以下を使用しました。

またデータの数も影響する可能性を考えてデータは以下のようなものを使用した。

  • users
    • 件数:10000
    • テーブル構成:create table users(id integer primary_key, name text not null);
  • tweets
    • 件数:10000
    • テーブル構成:create table tweets(id integer primary_key, content text not null, user_id integer);

なお、tweetsのuser_idはランダムにしているためv1とv2とで取得する件数は若干違います(ただしその差は2件のみ)

調査結果

f:id:gamelinks007:20211027215459p:plain

以下のリクエストをそれぞれのエンドポイントに投げたグラフが上のものです。

ab -n 10000 -c 50 <エンドポイント>

なお、v1とv2それぞれのリクエスト成功数は以下の通りです

v1: Total of 3305 requests completed(17:49に開始)
v2: Total of 5588 requests completed(17:50に開始)

傾向としては - v1 - 全体的にヒープ上のメモリを使う - ヒープのオブジェクト数はv2より少ない - GCの呼び出し回数はv2より多い - v2 - 全体的にヒープ上のメモリはv1より使用しない - ヒープ上のオブジェクト数はv1に比べてかなり多い - GCの呼び出し回数はv1より少ない

総合するとv2のほうが総合的なパフォーマンスは上っぽい。リクエストをさばいた量も多く、且つヒープ上のメモリもv1に比べると少ないのも評価できるポイント。

ただv2はGC自体の呼び出し回数が少ないので他のクエリも同時に捌いている状態だとパフォーマンスが悪くなる可能性があるかもくらい……?

おわりに

トータルで見るとgorm v2のほうがパフォーマンスが上なので、これからGoでWebアプリ開発とかするのであればgorm v2使うほうが良さそう。