くらしのマーケット開発ブログ

「くらしのマーケット」を運営する、みんなのマーケット株式会社のテックブログ。積極採用中です。

SQL を一定間隔で実行する

夜ご飯んンンンンンンンンンンンンンンッ!食べれないやつ😐
夜ご飯んンンンンンンンンンンンンンンッ!食べれないやつ😐

こんにちは、バックエンドエンジニアの @akira です。
データを自動で更新するなど、 SQL を一定間隔で実行したいケースがあり、今回はその方法を調べてみました。

前提条件は以下です。

  • PostgreSQL 9.3~
  • PGPASSWORDhost, port, username, dbname は省略
  • 以下の SQL を実行
update "Fruits" set updated_at = now() where id = '123';

bash

watch -n n COMMAND で COMMAND を n 秒ごとに実行できます。

COMMAND 部分はダブルクオートで囲むこともできます。
watch -n 10 "ls -l" # 10秒ごとに ls -l を実行

上述のクエリを実行する場合は次のようになります。

watch -n 60 psql -c "update \"Fruits\" set updated_at = now() where id = '123';"

エスケープがちょっと辛いですね。
watch の COMMAND 部分をダブルクオートで囲むと、さらに大変になりそうです。

psql

PostgreSQL 9.3 から \watch メタコマンドが追加されました。12 系でも使えます。

参考:\watch [ seconds ]

QUERY; \watch n で QUERY を n 秒ごとに実行できます。
先ほどのクエリを実行する場合は次のようになります。

update "Fruits" set updated_at = now() where id = '123'; \watch 60

エスケープ不要で、可読性も高いですね。

おまけ:redis-cli

redis-cli -r n -i s COMMAND で COMMAND を s 秒間隔で n 回実行できるようです。
-i を指定しない場合は即時実行のようですね。

参考:Continuously run the same command

さいごに

MySQL も少し調べてみたのですが、Event Scheduler で実行する方法しかヒットしませんでした(他にやり方をご存知でしたら是非教えてください🙏)。

「何かを実現したい」という意思がないと、上記のやり方を知る機会はなかったのかなと思っています(「30 分に一度、手動でコマンドを実行すればいいや」では決して調べることはなかったでしょう)。

業務でこのような機会を逃さずに、一つ一つ積み上げていきたいですね。

私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。
ぜひ コーポレートサイト までお気軽にご連絡ください!

pip install Flask-Injector ができない! を解消した

f:id:curama-tech:20200713191723p:plain

こんにちは。バックエンドエンジニア / SRE のまのめです。
先日、弊社のテスト環境「 tako 環境 」が焼けなくなり(*)、それについて調査・解決したことをまとめました。

* tako 環境を焼く = 社内用語で、テスト環境を作成/更新すること

状況

python3.5 で動くアプリケーションの tako 環境 を焼く際、 ansible のタスクが失敗するようになりました。

ansible のログを追うと、以下のようなエラーが出力されていました。

ERROR: You need Python 2.7 or 3.4 to install the typing package.

----------------------------------------

:stderr: Command \"python setup.py egg_info\" failed with error code 1 in /tmp/pip-buikd-XXXXXX/typing
You are using pip version 7.1.2, however version 20.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

複数回、複数環境で試したのですが、どうやら Flask-Injector の pip install ができなくなっており、 typing というモジュールの install でコケているようでした。

原因

先程も述べたように、アプリケーションは python3.5 系で動いています。
このアプリケーションで Flask-Injector を利用していますが、ある程度歴史もあるため若干バージョンが古めでした。

また、この現象が起きたのが 2020 年 7 月 10 日 で、 typing モジュールはその日にアップデートがありました。
ここで、typing モジュールの このときの最新版(3.7.4.2)の Project description に新しくこんな注意が記載されていました。

For package maintainers, it is preferred to use typing;python_version<"3.5" if your package requires it to support earlier Python versions. This will avoid shadowing the stdlib typing module when your package is installed via pip install -t . on Python 3.5 or later.

typing - pypl

さらに、 Flask-Injector の該当バージョンのモジュールの requirements を見たら、以下のようになっていました。

install_requires=['Flask', 'injector>=0.10.0', 'typing'],

flask_injector/setup.py at v0.10.1

はい、 Flask-Injector のこのバージョンでは、 typing のバージョンが固定されていませんね。

つまり、

Flask-Injectortyping のバージョンが固定されていないために最新版が入る
=> typing の最新版は python3.5 で入れられなくなった
=> pip install がコケる

ということだったのです。

そして解決へ

typing のバージョンをこちらが定義する requirements で無理やり固定してもよいのですが、ほかのモジュールでまたこういう事があると面倒だな…と思っていました。 そこで試しに、 pip install --upgrade pip setuptools をしたら、直りました。

このとき急いでいたこともあり、なぜそれで解決するのかを詳しく調べませんでしたが、おそらく setuptools がいい感じに働いてくれるのだと予想されます。 なので、 pip install する直前に setuptools をアップグレードするように ansible のタスクを修正し、 tako 環境 は無事直りました。

感想

こういったモジュールが古くて起こる不具合には、今回のようにその場しのぎな解決ではなく、根本的な解決であるモジュールのアップグレードで対応したいです。
しかし、緊急性が高い場合はひとまず今回のように処理し、時間をかけてモジュールのアップグレードの検証を進めて、根本解決できるといいなと思いました。

サービスが大きくなっていくとなかなかモジュールのバージョンにまで目を向けられなくなっていきますが、こういうことが本番で起きる前に、定期的に振り返る時間を作っておきたいですね。

エンジニアの「ドキュメントよりコード書きたい」を本気で解決してみた!

f:id:curama-tech:20200710184201p:plain

こんにちは、みんなのマーケットでCTOをしている戸澤です。

今回は、長年に渡って整備できなかった開発ドキュメントを、全員で整備する取り組みをはじめた、という内容です。

本記事は、6/10に開催した「失敗に学べ!くらしのマーケットの開発「失敗」LT会 vol.1」でのLT内容を再構成したものです。

課題

テクノロジー本部の長年の課題の1つに、「ドキュメントがない」 というものがあります。 ドキュメントがないと、

f:id:curama-tech:20200710184255p:plain

開発や環境構築などのわからないことは、Slackや口頭で聞く必要があります。 この状況では、教える側がその対応に都度時間を使う必要があり、また、内容も記憶頼りになり正確かどうか保障ができません。 特に教える側は往々にして忙しいことが多く、聞く側からすると、聞きづらい雰囲気の場合があり、ゆえに、聞く側が自己解決を試み時間がかかったり、聞かずに放置されてしまうということが起こります。

反対に、ドキュメントがあると、

f:id:curama-tech:20200710184306p:plain

聞く側が自主的に探せるようになり、また、探せなかったとしても、教える側が「xxxで検索してみて」と、キーワードを伝えることで解決できます。 それにより、教える側が都度対応していた時間を減らすこと、聞く側の聞きづらさの解消ができます。 また、内容が記憶頼りではなくなり、内容の間違いや忘れを防止できます。 さらには、教える側の使える時間が増えるため、ペアプロなどより価値の高い時間の使い方ができるようになります。

このようなメリットがあるとわかっていても整備が進まないのが、ドキュメントです。

どうすれば、ドキュメントを充実させていくことができるのでしょうか。

そんな中、ある方から次のようなアドバイスをもらいました。

転機

f:id:curama-tech:20200710184317p:plain

f:id:curama-tech:20200710184329p:plain

たしかに、コードとドキュメントどっちに時間を使うべきか迷ったり、一人で書こうとして整備が進まなかったドキュメントですが、みんなで同時に書くのであれば、時間の設定や全員の責任として、書くことができるはずです。

これは良いのではないか、ということで実施してみました。

やってみた

実施にあたって、次の3つのポイントを決めました。

  1. ドキュメントのフォーマット
  2. ドキュメントの項目
  3. イベント化する

順番に、 f:id:curama-tech:20200710184343p:plain

まずはゴールを決め、そこに求められるドキュメントのフォーマットを決めます。 今回達成されるべきゴールは、そのドキュメントを他の開発チームが読んで理解できることです。 現在の状態では、フォーマットを詳細に決めてもそれを全て守ることに頭を使ってしまうので、ゴールが達成に必要な必要最低限のものだけにします。

記事は、機能単位の粒度で1つの記事にまとめます。 記事が長くなる可能性がありますが、それよりも記事が分散し探す手間が増えたり、更新漏れの発生を防ぐためにまとめます。 今後、記事が長くなってから分割することを考えればよく、まずは記事を書くことに集中します。 その他、事実と感想を分けることや、図や表を使ってわかりやすくすることなど、基本的なことだけ決めます。

f:id:curama-tech:20200710184357p:plain

次に、ドキュメントの項目出しをします。 チーム毎にこれまで扱った開発内容のドキュメントを書いていくため、まず項目の抜け漏れがないか確認をするため、同じ項目を複数名で同時に作成してしまうことを防ぐために行います。 どの項目から作成に着手するかはチームで判断して大丈夫です。 ただし、2,3回...と継続して取り組んでいき、どの項目もいずれ書くことになるので、優先度は決めなくても問題ないと思います。

f:id:curama-tech:20200710184406p:plain

最後に、ドキュメントを書くことをポジティブに認識していけるように、この取り組みをイベント化していきます。 また、ゴールが達成されているかの確認と、成果を出すことに意識を向けるために、ほかの開発チームからレビューをもらうようにします。 ドキュメントは全員で作成、更新していくものであり、全員が参加すること、という意識付けでもあります。

レビューが終わったら、全員で簡単にドキュメントの概要を発表しあいます。

結果

「xxxで検索してみて」と言えるタイミングが増えました。 結果として、教える側が都度付きっきりで教えていた時間を、他のことに使えています。 また、ドキュメントのレビュー時に、レビュワーが初めて知る内容もあり、そのタイミングからすでに理解が深まっていく様子でした。

今年4月に1回目を開催し、毎月1回開催し、6月までに計3回開催しました。

ドキュメントは増えてきましたが、カバレッジをもっと上げるために今後も月1回で継続開催し、カバレッジが高まってきたら数ヶ月に1回の開催のように、頻度を落としてもいいと思います。

おわりに

そもそもドキュメントがないとドキュメントの有用性を理解できなく、ドキュメントが書かれないという悪循環に陥ると思いますが、ドキュメントのカバレッジが上がり、日常的に使うようになってくると、逆にドキュメントがないことが目立つようになってくると思います。 そうなると、このような取り組みをしなくても、その気持ち悪さから自然とドキュメントを作成し、そこを補完しようとする気持ちに私はなると考え、今後はカバレッジが上がるにつれて、ドキュメントを書くカルチャーも根付いてくるのではないかと思いました。

動画初心者がAWS Elemental MediaConvert使ってみた!

f:id:curama-tech:20200703183513p:plain

こんにちは、みんなのマーケットでCTOをしている戸澤です。

今回は、動画の知識がない初心者がAWS Elemental MediaConvertを使って動画変換してみた、という内容です。

ことのはじまり

先日、仕事で動画撮影の機会があり、合計6時間(1920x1080, 60fps)ほど撮影しました。 動画撮影の機会も、ましてや6時間も撮影する機会はこれまでなく、データ量を特に考えずに撮影してしまい、いざSDカードを開いてみると、6時間かつ60fpsということもあり、データ量が65GBとなっていました。

困ったのは、GPUが積まれていたり、SSDの空き容量が十分といった動画編集に向いたPCが手元にはなく、普通のPCでこのまま処理すると、編集や書き出しに相当の時間がかかることが予想できました。SSDの空き以外にも、編集は元のサイズでできたとしても書き出しは時間がかかりそうで、とはいえ、一度、編集のためにサイズの小さい720pにするだけでも6時間もあるとこれも変換に時間がかかることが予想できました。

解決案

そもそもの原因はマシンスペックが動画向けでないことであり、解決策として次の3つを検討しました。

  1. マシンスペックを上げる
  2. EC2のGPUインスタンス + ffmpeg
  3. AWSの動画変換サービス

1,2に関してはGPUやどこまでの性能が必要かを調べる必要がありますが、3であればマネージドであり性能面は気にせず、また、物理デバイスを用意する時間も省けるのではないかと考え、今回は3を選択することにしました。

AWSの動画変換サービス

AWSのメディア系サービスのうち、動画変換ができそうなのはこの2つでした。

違いの明確な説明を発見できなかったですが、簡単に次のようです。

  • Amazon Elastic Transcoder
    • 基本的な動画の変換ができる
  • AWS Elemental MediaConvert
    • 動画の変換の他に、結合、イメージの挿入などができ、Transcoderよりも高度
    • Elastic Transcoderのページの冒頭からMediaConvertを推奨している表記があり、今後はMediaConvertがメインになっていく?

今回は次の2つの点を要件とし、

  • ローカルで扱いやすくするためにデータ量を減らすこと
    • 720p, 30fpsに変換する
  • 4GB毎に分かれている動画ファイルを連結すること

この要件を満たすことができる、MediaConvertを使ってみることにしました。

MediaConvertの料金は、出力ファイルの時間、1分単位での課金です。 また、ベーシック階層とプロフェッショナル階層があり、Pro と記載のあるオプションやメニュー、パラメータを選択するとプロフェッショナル階層での課金になるようです。

f:id:curama-tech:20200703183541p:plain

今回、6時間、1080p、60fpsの動画を、同じ6時間、720p, 30fps, AVC(H.264, ベーシック階層)コーデックに変換すると次の課金になります。

6(時間) * 60(分) * 0.017(米ドル/分) = 6.12(米ドル)

(東京リージョン、2020/07/02現在)

使ってみた

MediaConvertによる動画変換の流れは、次の通りです。

  1. 入力ファイル(変換元のファイル)をS3にアップロードする
  2. MediaConvertでジョブを作成、実行する
  3. ジョブ完了後、出力ファイル(変換後のファイル)がS3にアップロードされる

(初回利用の場合はジョブ作成前に、MediaConvert用のIAMロールの作成が必要です。)

1,3はそのままの意味なので、記事では、2のジョブの作成と実行について取り上げます。

入力ファイルの設定

まず、ジョブ一覧にある、ジョブの作成 から作成画面に移ります。 f:id:curama-tech:20200703183603p:plain

ジョブの作成画面で、入力の追加を押下し、入力1,2,3...に、入力ファイルのS3パスを設定してきます。 今回は複数の入力ファイルの結合もするため、入力を複数作成しており、入力の番号順に結合が行われます。

f:id:curama-tech:20200703183619p:plain

全ての結合するファイルを設定したら、入力ファイルの設定は完了です。

次に出力ファイルの設定をしていきます。

出力ファイルの設定

出力グループの追加を押下すると、グループの選択モーダルが表示されます。 今回はファイルグループを選択します。 f:id:curama-tech:20200703183638p:plain

次に、File Group送信先に、出力ファイルを作成するS3パスを指定します。 f:id:curama-tech:20200703183649p:plain

出力ファイルの設定は完了です。

次にエンコードの設定をしていきます。

エンコードの設定

Output 1 をクリックすると、エンコードの設定画面が表示されます。

ざっと眺めてみると、コーデックや解像度など知っているものもありますが、 f:id:curama-tech:20200703183713p:plain

画面下に行くと、知らない設定値が並んでいます。 画面最下部を見ると、ノイズ低減、イメージ挿入、色補正もできるようです。 f:id:curama-tech:20200703183728p:plain

現状は、ゼロベースで設定できるだけの知識をもっていないので、今回はプリセットを使うことにしました。

設定画面上部のプリセットから適切なものを選択します。

f:id:curama-tech:20200703183741p:plain

今回は、 720p, 30fps, AVCで出力したいため、次のプリセットを選択しました。

System-Generic_Hd_Mp4_Avc_Aac_16x9_Sdr_1280x720p_30Hz_5Mbps_Qvbr_Vq9

f:id:curama-tech:20200703183753p:plain

エンコードの設定は完了です。

最後に、IAMロールの設定をします。

IAMロールの設定

ジョブの設定 からIAMロールを設定します。

f:id:curama-tech:20200703183808p:plain

ここまでで必要な設定は完了しました。

実行と結果

ジョブを開始し、ジョブ一覧でCOMPLETEになると、S3に出力ファイルが作成されている状態です。

今回、長さはバラバラですが動画を3本、計6時間分を並列で変換処理しました。

その結果、動画1本の処理時間はおおよそ60〜90分で変換でき、 6時間分の全ての動画ファイルのサイズは合計で9.9GBになり、ローカルで扱える状態になりました。

おわりに

今回、はじめてAWSの動画関連のサービスを使ってみました。

MediaConvertは、プリセットがあったため、初心者でも動画の変換を行うことができました。 今回のような長時間の動画変換や、また、システムにアップロードされる動画の変換など、安定した動作環境、スケールする動作環境が要件になる場合にMediaConvertのようなマネージドサービスを選択するのは正解と思いました。

今回は仕事で使用しましたが、運動会など家庭で長時間の動画を撮ったときも使えそうですね。

リモートワークなので VSCode で Remote-SSH しながら LiveShare を試す

f:id:curama-tech:20200407155134j:plain

バックエンドエンジニア 兼 SRE のまのめです。

ご時世もあり、弊社の東京オフィスではリモートワークが推奨されています。
オフィスではデスクトップの Linux PC を使っている人が大半なので、リモートワークでは ssh でオフィスの PC にアクセスして作業する人が多いです。

これで基本的には問題ないのですが、困りの種になっているのが「コーディングのことを相談しづらい」というところです。
オフィスにいれば PC を持っていくなりして、コードを見せながら説明できるのにな〜。

ということで、VSCode の LiveShare 機能を、リモートワークで試してみました!

やってみる

まず先に、ホスト側が共有したいのは ssh でつないだ PC にあるコードなので、Extension のRemote - SSHを入れて、ssh で接続した画面を用意しておきます。
(画面左下に、「SSH:HOSTNAME」と出ていることを確認します)
そしてその画面上で、LiveShare の Extensionを入れます。

導入自体に関しては、公式の Quick Start を見るのが早いです。
なお作業する人が全員、LiveShare の Extension を入れておく必要があります。

ホスト側は、LiveShare のアイコンからメニューを出して、「コラボレーションセッションの開始」をクリックします。
初回は認証とかが必要なので、GitHub のアカウントなどで認証をしておきましょう。
準備ができると、クリップボードにリンクがコピーされるので、それを相手に伝えましょう。
リンクが分からなくなったらこのマークをクリックでコピーできます。

f:id:curama-tech:20200407155200j:plain
LiveShare の招待リンク

URL を受け取った側は、そのリンクを踏むと LiveShare されたコードに入れます。

これだけです!

やってみた感想

音声通話も Extension でできるようですが、今回試したときは Slack コールで音声通話をしながらコードを見ました。
ホスト側のカーソルや選択範囲などがハイライトされるので、「ここのコードが…」みたいなのを説明しやすかったです。

f:id:curama-tech:20200407155210j:plain
(思いっきりプロダクトコードなので、モザイクをかけています)

そして結構驚きなのですが、Remote-SSH で接続したコードであっても、大変スムーズにアクセスできて、レイテンシも少ないという感触です。
ssh over VPN という状態なのにもかかわらず、重いと感じたことがありませんでした。

今回はコーディングの相談という形でしたが、今後ペアプロやモブプロをすることになってもこれを使いたいです。
僕は普段 Emacs でコーディングをしているのでほとんど VSCode を使わないのですが、この機能のために環境だけでも整えておこうかなと思います。

まとめ

VSCode の LiveShare は、大変便利で作業がはかどりました。
Remote-SSH しながらでも快適にできることがわかったので、みなさんもぜひ試してみてください。

僕たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。
こういった「これできるようにしたい!」をまずやってみる、という仲間がたくさん在籍しています。
一緒にくらしのマーケットを盛り上げたい!という方はコーポレートサイト https://www.minma.jp/ までお気軽にご連絡ください!