Rocket.Chatでファイルアップロードを頻繁に使うならば、アップロードしたファイルの保存先はデフォルト(GridFS)から変えた方が良い

Rocket.Chatでアップロードしたファイルの保存先は、最新(3.16.3)だと下記の5種類から選ぶ形になっています。

  • GridFS
  • FileSystem
  • Amazon S3
  • Google Cloud Storage
  • WebDAV

設定方法などは、下記にまとまっています。

デフォルトはGridFSです。GridFSでは、ファイルをチャンクに分割してMongoDBのドキュメントとして登録するので、新たな設定が不要(Rocket.ChatはMongoDBが必須)で手軽に使えるのですが、MongoDBに負荷を与えることにもなります。

そのため、Rocket.Chatでは、ファイルアップロードを頻繁に使うような場合にはGridFSの利用を推奨していません。

  • Recommendations for File Upload - Rocket.Chat Docs

    Though GridFS is used in rocket.chat for file storage because MongoDB offers this functionality with zero configuration but GridFS is not recommended for day to day file storage needs in a production environment because it puts an immense amount of load on the database.

Rocket.Chatがちょっと重たくなってきたとか、ファイルアップロードが遅かったり、エラーになったりするような場合には、GridFSを疑ってみると良いと思います。
デフォルトがGridFSなので、問題が起きて気が付く、、といった場合が多そうですね。Rocket.ChatのGitHubやForumでもGridFSに関する問題が何度かやりとりされているようでした。

GridFSからの変更ですが、FileSystemが一番手軽にできる変更だと思います。適当なフォルダ切って、Rocket.Chatからアクセスできるように権限を与え、Rocket.Chat上からフォルダを指定するだけです。再起動はいりません。
ただし、Rocket.Chatを複数台で運用している場合、すべてのRocket.Chatサーバから見て同じパスになるように設定(ネットワークフォルダ等)する必要があります。

2021年5月から6月にZennで書いた記事

2021年5月から6月までの記事

Redmineでステータスと連動して進捗率と担当者を変更する(View customize plugin)

View customize pluginで、(個人的に)一番便利だと思っているスクリプトです。
チケットの担当者を切り替えながら進めていくような場合には、ほんんんんとに便利なので、ぜひ試して欲しいです。

GoでCSVファイルを処理するCLIのツール(csvt)を作りました

CSVファイルを処理するcsvtというCLIのツールをGoで作りました。
作り始める時点で用意しようと思っていた機能が揃ったので紹介します。
(2021-12-07追記) その後欲しい機能が増えて、サブコマンドが倍増したので、現在の情報で更新します。

csvt

csvtはCSVファイルを処理するCLIのツールです。
Goで実装しています。

Goの勉強のために個人で作ったものですが、今所属するプロジェクト内でも利用してもらっています。

下記のようなサブコマンドを用意しており、CSVを編集するうえでたいていのことは、これらコマンドで事足りるようになりました。

  • add 列を追加します。
    固定値や他の列の値のコピー、テンプレートを使った値の生成(複数列の値を結合したものとか)も出来ます。
  • choose 列を選択して新しいCSVファイルを作成します。
  • concat 2つのCSVファイルを結合します。
  • count レコード数をカウントします。
    列を指定して値が存在するものをカウントすることもできます。
  • exclude 他のCSVファイルに存在する行を除外します。
  • filter 条件に一致する行に絞り込みます。
    条件には正規表現や他の列との比較も書くことができます。
  • head 先頭の数行を表示します。
  • header CSVファイルのヘッダを表示します。
  • include 他のCSVファイルに存在する行に絞り込みます。
  • join 指定した列をキーとして、CSVファイルのレコードを結合します。
    EXCELのVLOOKUPに似ています。
  • remove 列を削除します。
  • rename 列名(ヘッダ)を変更します。
  • replace CSVファイルの値を正規表現を使って置換します。
  • slice 指定した範囲の行を切り出します。
  • sort 指定した列の値でソートします。
    複数の列を使ってソートすることもできます。
  • split 指定された行数毎に分割します。
  • transform CSVファイルのフォーマットを変更します。
    デリミタ、セパレータ、クォート、文字コードなどを変更することが出来ます。
  • unique 指定した列の値を利用して重複するレコードを取り除きます。

一番大変だった気に入っているコマンドはjoinです。
ExcelのVOOKUP的なことができます。

$ csvt join -1 INPUT1 -2 INPUT2 -c COLUMN -o OUTPUT
Usage:
  csvt join [flags]

Flags:
  -1, --first string     First CSV file path.
  -2, --second string    Second CSV file path.
  -c, --column string    Name of the column to use for joining.
      --column2 string   (optional) Name of the column to use for joining in the second CSV file. Specify if different from the first CSV file.
  -o, --output string    Output CSV file path.
      --usingfile        (optional) Use temporary files for joining. Use this when joining large files that will not fit in memory.
      --norecord         (optional) No error even if there is no record corresponding to sencod CSV.
  -h, --help             help for join

例えば、input1.csvとして下記内容のCSVファイルと、

UserID,Name,Age,CompanyID
1,"Taro, Yamada",10,2
2,Hanako,21,1
3,Smith,30,2
4,Jun,22,4

input2.csvとして下記内容のCSVファイルを用意して、

CompanyID,CompanyName
1,CompanyA
2,CompanyB
3,CompanyC
4,"AAA Inc"

CompanyIDの値を使って結合します。

$ csvt join -1 input1.csv -2 input2.csv -c CompanyID -o output.csv

できあがったoutput.csvは下記のような内容になります。
input1.csvを基準として、input2.csvの内容を足していくようなイメージです。

UserID,Name,Age,CompanyID,CompanyName
1,"Taro, Yamada",10,2,CompanyB
2,Hanako,21,1,CompanyA
3,Smith,30,2,CompanyB
4,Jun,22,4,AAA Inc

--usingfile というオプションを利用すると、メモリにファイル全体を載せることなく結合するので、どんな大きなファイルでも問題なく処理できます。(数GBのCSVファイルでも使用メモリは数十MB)

他のコマンドも含め、詳しい利用方法はREADMEをご参照ください。

csvt でサポートするフォーマット

csvt の特徴的なところとして、柔軟にフォーマットが指定できるというところがあります。

CSV、TSVといった良くあるフォーマットだけでなく、マイナーなフォーマットにも対応するために、フォーマットとして下記が指定できるようになっています。
全てのサブコマンド共通のフラグです。

Global Flags:
      --delim string      (optional) CSV delimiter. The default is ','
      --quote string      (optional) CSV quote. The default is '"'
      --sep string        (optional) CSV record separator. The default is CRLF.
      --allquote          (optional) Always quote CSV fields. The default is to quote only the necessary fields.
      --encoding string   (optional) CSV encoding. The default is utf-8. Supported encodings: utf-8, shift_jis, euc-jp
      --bom               (optional) CSV with BOM. When reading, the BOM will be automatically removed without this flag.

技術的なところ

Cobra によるサブコマンドの実装

Cobra を利用することで、CLIでのサブコマンドの実装が簡単にできました。

cobra add で追加される雛形だと、サブコマンド毎のテストが書きずらかったので変えています。
root側にサブコマンドに関する処理を追加しなければならないのが煩雑ですが、テスト毎にサブコマンドを生成したかったのでやもえずです。 (ほんとはもっと良い方法があるのかもしれない、、)

フラグをソートしたくなかったり、エラーメッセージの表示タイミング変えたりとか、、いろいろ調べることもありましたが、Cobraに関する情報はたくさんあったので、やり方が見つからないといったようなことはありませんでした。

Bolt を利用することで大きなmapをメモリから追い出す

joinsortコマンドでは、CSVのレコードを全部読み込んだうえで処理しなければならず、それをメモリに載せてしまうと、巨大なCSVファイルを処理するときにメモリが足りなくなりかねません。

キーバリューストアのBoltを使うことで、mapをメモリの外(ファイル)に追い出すような実装も用意し、オプションで切り替えられるようにしました。

BoltはAPIがシンプルなのもあってか、迷うことなく簡単に利用することができました。

ASCII Table Writer

headコマンドでCSVの先頭数行を表形式で表示したかったので、何か良いライブラリが無いかなと調べたところ、ASCII Table Writerというライブラリを見つけました。

全角文字にもちゃんと対応しているので、日本語で崩れるといったようなこともなく、簡単に表形式での表示が実現できました。

go-customcsv

細かいフォーマットのカスタマイズが encoding/csv だと出来ないので、別途CSVパーサを書いてそれを利用するようにしました。

他のCSVライブラリもいくつか確認しましたが、要件満たしている&良く使われてそうでこれなら安心そう、、ってのが見当たらなかったので、Goの勉強も兼ねてということで、、

第20回 redmine.tokyo勉強会で『Redmine issue assign notice plugin の紹介』というタイトルで発表しました

第20回 redmine.tokyo にて、『Redmine issue assign notice plugin の紹介』というタイトルでLTさせていただきました。

資料はこちら。

Redmine issue assign notice pluginは、チケットの担当者を切り替えて進めていくようなプロジェクトでは、とても有用なプラグインだと思っていますので、今回このLTを見て試してみようという方がいたらうれしいです。

f:id:onozaty:20210523182619p:plain

今回の勉強会は、ところどころ抜けながらの参加(リモートだから家のことを途中で出来るので助かる)でしたが、聴いた発表はどれも良いものでした。
その中でも特に skys さんの「新型コロナウイルス感染者情報管理」は、Redmineをカスタマイズすることで、コロナウイルス感染者情報管理するという、とても面白い事例でした。

Redmineのカスタマイズ性の高さからか、開発以外の用途でも活用できる事例は多いですね。

2021年3月から4月にZennで書いた記事

2021年3月から4月までの記事

ShortcutKey2URLを使ってブラウザ操作を快適に(Chrome/Firefox拡張機能)

愛用しているShortcutKey2URLというChrome/Firefox用の拡張機能の紹介記事です。
個人的にはとても便利だと思っているので、もっといろんな人に使ってもらえたらなぁと思っています。

Gradle Shadow Pluginで作成したfat/uber JARで、複数のJDBCドライバがロードできない

Gradle Shadow Pluginで、デフォルトだとMETA-INF/services配下が上書きされてしまい、ハマった際の記事です。
忘れたころにまた嵌りそうです、、

社内勉強会で「最近作ったもの」というタイトルで発表しました

社内勉強会で最近作ったものってタイトルで、Goで作ったツールやRedmine issue assign notice pluginについて発表しました。

www.slideshare.net

在宅勤務で通勤時間&肉体的な負荷が無くなったことで、趣味でコード書ける時間が今までより増えたなーって思います。
あと、Goはちょっとしたツールを作って配布するためのものが全て揃っていて素晴らしいです。

Goでファイル一覧+αを出力するCLIのツール(filist)を作りました

Goの勉強も兼ねて、適当な課題見つけてCLIツールをちょこちょこ作っているのですが、他の人が使っても便利かもしれないものが出来たので紹介します。

指定したディレクトリ配下のファイル一覧を再帰的に表示するツールです。

$ filist -s -M .
a.txt   24  3d3a42d900823afcfdfeb6de338bcec1
b/1.txt 81  ae23e0b40e773ac132f477f661e89b86
b/2.txt 163 494ba81d0d828ff9a244da627b5ece47

ファイルパス以外にも、サイズ、更新日時、MD5、SHA1などといった情報も一緒に出力できます。

オプションは下記の通りです。

Usage: filist [options] directory ...
options
  -r, --rel      Print relative path (If neither 'rel' nor 'abs' is specified, 'rel' will be printed first column.)
  -a, --abs      Print absolute path
  -s, --size     Print file size
  -m, --mtime    Print modification time
  -M, --md5      Print MD5 hash
  -S, --sha1     Print SHA-1 hash
      --sha256   Print SHA-256 hash
  -h, --help     Help

オプションの指定順に情報が並ぶので、例えば先頭にMD5で、その後にファイル名、、といった指定もできます。

$ filist -M -r .
3d3a42d900823afcfdfeb6de338bcec1  a.txt
ae23e0b40e773ac132f477f661e89b86  b/1.txt
494ba81d0d828ff9a244da627b5ece47  b/2.txt

全てのファイルにmd5sumかけたい、、っていうようなときに、コマンド組み合わせてワンライナーで書けなくないですが、こういったツール用意しておくと便利かなーって思って作りました。
Goだと各OS用の実行ファイルをシングルバイナリで簡単に提供できるってのがほんと素晴らしいです。