sinatra-formkeeperで2つの入力内容が異なることをvalidateする

最近業務で、とあるwebツールを作っており、いわゆる入力画面が必要になった。

今回はRubyのプロジェクトだったので、アプリケーション自体はsinatra
そのvalidatorとしてlyokatoさんのsinatra-formkeeper を使った。

これが大変便利!
さすがFormvalidator::Simpleを作っただけあって、
必要なものは揃っているし、使い方も上述のblogエントリを読めば、ほぼわかる。

ただ、「 入力値A入力値B が異なること」ということをしたい場合にこれをvalidateする機構がなかった。
今回はこれがピンポイントで欲しい機能だったのでサクっとPRを投げて、取り込んでもらった。

github.com

Validatorとしてのコア機能はformkeeperに切り出されているので、PR自体はそちらに対してのものになっている。

さっそくmergeしてもらい、rubygemsからも拾えるようになった。
使い方はこんな感じ。
テストも合わせて貼っておきます。

gist.github.com

実装自体は99%が既存の機能である same のパクリ。
same は上述のブログ例に書かれている通り、パスワード確認の時などに用いられるでしょう。
対して今回の diff は例えば登録しているメールアドレスの更新や、パスワードの定期更新などに用いられる事を想定してます。
(※ パスワードを定期的に更新するセキュリティポリシーとその運用の是非についてはここでは言及しません)

まぁ、今回の業務ではそのどちらでもないケースで必要になったパッチ送ったのですがw
なので、きっと他でも有用なところがある(かもしれない)!

繰り返しになるけど、sinatra-formkeeper 自体がそもそも便利なので、
まとめとしてはそれが便利ということが伝われば良しです。

YAPC::Asia2015で「 Perlがメインじゃない 現場でもPerlを使う (AdTech現場編)」というトークをしてきました

タイトルでほぼ出オチですが、2年ぶり4回目となるYAPC::Asiaでの発表をしてきました

www.slideshare.net

4回目とか言いつつ、内容はまだまだだし、発表自体も緊張しまくりでした。
前週のうちに資料作りと社内リハーサルを終えていたのに、前日とかにで結構な分量の修正してた。。

togetter.com
いくつかコメントも頂いていてありがとうございます。 内容としては、現職での直近業務についてお話しするという感じでした。
はっきり言って地味な業務だし、伝わりづらい内容ではあると思いますが、何かの参考になれば幸いです。

YAPC::Asiaも10周年。
とうとう今回は2000人規模に。自分の発表した会場でさえ、一番小さいのに100人キャパ。
5トラックという並列性も過去最高。とんでもないイベントですね。

自分の発表が2日目午後だったこともあり、2日目のトークは聞けないのもあったりして、 リファクタだったりGoの話だったりは後ほど確認したいと思いました。
例年通りの幅広い内容で充実していたのではないかと。

ビックサイトは何気にほとんど行った事なかったですが、スムーズな運営(無線ネットワーク、通訳、ボランティアスタッフの対応 などなど) のおかげで非常に快適でした、これは例年通り!

今の自分があるのはYAPC(と特にyokohama.pm)が一定割合占めているなと思うと、
来年以降も何かしらの催しが欲しいと素直に思います。

Thanks YAPC::Asia!!

Perlでcrontabを意図通り書けているか確認するテストを書く

TL;DR

書いたcronが意図通りの時間に動くかを簡易的にテストするもののPHP版に元に、Perl版のモジュールを書いてgithubに置きました(未CPAN UP)

追記: CPANにもUPしました

これは何?

意図としてはPHP版と同じです。

PHP版の時には使ったライブラリ(Cron\CronExpression)が 「crontab宣言と基準時刻を食わせると、その時刻より最も直前にcronが動いた時間と最も直近でcronが動く予定の時間を返してくれる」 のでこれとのマッチングをテストしていました。

今回のPerl版はsongmuさんが作成されたParse::Crontabを用いてます
これは「crontab宣言を食わせて、指定時刻渡すと、その時刻にcrontabが動くかどうかを返してくれる」ので、これとのマッチングになります

サンプルコード

サンプル置き場 にも置いてあるのですが、

#!/usr/bin/env perl

use strict;
use warnings;

use Test::More;
use Parse::Crontab;
use Test::Parse::Crontab::Simple;

my $crontab        = Parse::Crontab->new(file => './crontab.txt');
my $crontab_strict = Parse::Crontab->new(file => './crontab_strict.txt');

ok $crontab->is_valid;
match_ok $crontab;

ok $crontab_strict->is_valid;
strict_match_ok $crontab_strict;

done_testing;
*/30 * * * * perl /path/to/cron_lib/some_worker1
###sample 2014-12-31 00:00:00

0 23 * * * perl /path/to/cron_lib/some_worker2
###sample 2014-12-31 23:00:00

0 15 * * * perl /path/to/cron_lib/some_worker3

crontab記述の次の行に
###sample YYYY-MM-DD HH:ii:ss

の形式でそのcrontabが動くと思う時間を書いておくと、
意図した時間にcronが動くかどうかをテストすることができます

match_ok のメソッドを用いた際にはサンプルの時間記述は必須ではありません
記述がなければ該当のcrontabの宣言はテストされずに進みます

一方、strict_match_okのメソッドはcrontab宣言の直後に必ずサンプルの時間記述を求めます
記述がない場合にはテストがfailします

進捗

現時点では、サンプル記述はcrontab宣言ごとに1つしか想定していないため、あくまで簡易的なテストです

* 17 * * * perl /path/to/cron_lib/hourly_worker
###sample 2015-01-01 17:00:00

上記は毎日17時に1回動いて欲しいバッチに対して、それを期待した サンプル記述をしていますが、実はこのバッチは17時台に毎分動いてしまいます
それは意図通りではないのですが、そこまでのテストができてません
PHP版の時には少なくとも2つのサンプルを必要としていたので、上記パターンも 検知しやすかったですが、そういう意味だと今回のPerl版は少し弱すぎるかもしれない。。

この辺は是非フィードバックをいただきたいところです。

MySQLのint(3)とかint(10)とかint(50)とか

今日ふと見たschemaで、

letter varchar(16) DEFAULT NULL,

みたいのがあった時に、違和感があった。

この(16)っていう桁数って意味あるんだっけ・・?
なんか使われる領域は結局同じだったような・・?

結論から言うと、これは勘違いでした。
この違和感はint型の時のやつでした。

以下、実験コード。

gist0a701d3a4ba4c6c10331

create database test_lengthしてから
mysql -u root test_length < length_test.sql で食わせてください。

結果は

mysql> select * from varchar_length;
+----+------------------+-------------------+
| id | letter016     | letter256     |
+----+------------------+-------------------+
| 1 | 1234567890123456 | 1234567890123456  |
| 2 | 1234567890123456 | 12345678901234567 |
+----+------------------+-------------------+
2 rows in set (0.00 sec)

こっちは、ある意味想定通り。
16桁のところには、17文字目以降は入らない。
一方int型の

mysql> select * from int_length \G;
1. row
id: 1
number03: 100
number10: 100
number50: 100
number03_fill: 100
number10_fill: 0000000100
number50_fill: 00000000000000000000000000000000000000000000000100
2. row
id: 2
number03: 1000
number10: 1000
number50: 1000
number03_fill: 1000
number10_fill: 0000001000
number50_fill: 00000000000000000000000000000000000000000000001000
2 rows in set (0.00 sec)

違和感は原因はこの時のやつでした。
MySQLのint型の時には別に領域はそのままで表示の桁埋めのための表記ということ。
int(3) にしても1000は入るし、int(50)なんてのもできてしまう。

MySQL createtable int zerofill」あたりでググると色々でてくる。

戻ってまとめると、varcharの容量とか仕様のために桁数を検討することは正しい。

phpのsyntax checkとperlのuse check テスト

リポジトリ配下のファイルの内容を最低限保証するためのテストを書きました。
PHPで調べたところ、syntaxをチェックするそれっぽい関数がない。

正確に言うと、過去にはphp_syntax_checkというのがあったようだけど、5.0.5という結構な昔に廃止された模様。
代わりにコマンドラインから php -l hoge.php が推奨らしい。

なるほどーと思いつつ、推奨されてるならその通りに従って書いてました

php syntax check test

libというディレクトリ配下全般をチェックする前提です。
ファイル一覧を取得するのは1個前のエントリと変わらず。

ちなみにPerlでやろうとすると、perl -wc hoge.plになるんだろうけど、
リポジトリ配下に対してというアプローチの場合、pmファイルを対象としているハズ。
pmファイル群つまり各モジュールがloadできるかをチェックしたいという意図になると思うので、それに対しては Test::Moreの use_okによって実現できる

perl module use_ok test

本当はPHPの場合もロードが正しくできるかをチェックしたかったのだけど、前述のだとそこまでは見られない。
ただ、PHPにおいては vendor/autoload.php でドバっと読み込むのが主流っぽい気もするし、 Perl のように各個ごとに use を並べるのとは仕組みが違う気もするので、今回はこの形に落ち着きました。 

PHPでcrontabを意図通り書けているか確認するテストを書く

以下の環境と状況を前提にします

  • あるリポジトリにcrontabに設定したい内容をtxtファイル( cron.txt)を含めてコミットしている
  • コミットされたファイルがデプロイされるとその内容に基づいてデプロイ先サーバーでcrontabが設定される

よくある構成かと思います。
ここでコミットされているファイルに以下のような記述がありました。

* 13 * * * php hoge.php

この設定を書いた意図は、「毎日13時に hoge.phpを起動したい」でした。
しかし実際の挙動は「毎日13時台に毎分 hoge.phpが起動する」になります。

これに気づかないままコミットしてデプロイされてしまうと、本番サーバーに異常な負荷がかかったり、データ不整合が起こる可能性があります。

このリスクを少しだけ減らすためのテストを書きました。

php_cron_test

cron-expressionというパーサーがあったのでこれを用いています。
便宜的に $PROJECT_ROOT/cron_file 配下に cron.txt(群)がある想定とします。
その上でcron.txt内のcrontabの宣言の次に以下の2行を追加します。

  • ###prev YYYY-MM-DD HH:ii:ss
  • ###next YYYY-MM-DD HH:ii:ss

まず、「cron宣言の後にこの2行がないと落ちる」テスト項目が書かれています。
なので、ファイル内のすべてのcron宣言の後に2行追加する必要があります。
追加した2行には「2015年1月1日 0時0分0秒」から見て、

  • prev : 最も直前にcronが動いた時間
  • next : 最も直近でcronが動く予定の時間

を書きます。前述のパターンの場合だと、こんな感じです。

* 13 * * * php hoge.php
###prev 2014-12-31 13:00:00
###next 2015-01-01 13:00:00

つまり、「メモ書きを追加することで『設定した時間が意図通りか』をある程度まで自己確認すること」を目的としたテストです。
実際に、prevの設定値を「2014-12-31 13:59:00」にするか、
cronの宣言を「0 13 * * * php hoge.php」にしないとテストが落ちます。

試しに作ってみた系なので、色々問題はあるかと思っています。

  • cron.txtが汚れる
    • 嫌がる人は嫌がる
  • 意図とはズレていても結果的に期待値が同じprevとnext指定になるケースもきっとある
    • cron-expressionが指定時間からの前後時間を返すメソッドを用意してるためそれに合わせた仕様にしたのでこれは許容
  • 基準日だったり、パース用のprefixは割と適当
    • なので変更してもらって構わない

PerlだとTest::Crontab::Formatがあり、 これはcron.txtに余計な記述をすることなくcrontabのformatをチェックできるので便利です。
最初はこれっぽいものを探していたのですが、見つからなかったのと今回遭遇したケースは 「意図と違う時間の設定 = うっかりミス」だったので、こういうアプローチにしてみました。

YAPC::Asia 2014に行ってきました

blogに書くまでがYAPCです。
ここまで2個下から一緒。


もはや、YAPC専用blogになってる。。


今年はスピーカーではなく、イチ参加者(個人スポンサーになってみた!)
として参加してみました


単純な感想はうーん、なんだろう。
あまり楽しめなかったかなというのが率直な所。
きっとそれは個人の問題だと思うので、イベント自体に何か問題があったという訳ではないです。


客観的に見て良かった所
・安定のネットワークインフラ
・無限コーヒー&レッドブル
・HUB貸し切り!
・何気に空調コントロールも良かった。微妙な天候・気候の中で不特定多数の空間をコントロールしていたのにずっと適温だった気がする
・若い人も結構いた気がする


さて、内容についての感想を述べると、
トークの中には「既にブログなどで発表・公開している内容」に留まってしまうものもあります。
それに至る経緯とか今後の話とか、なんかしらの補足を聞ければ良いんですが、そうならない場合もある。
もちろん、イベント駆動開発ってあるし、それは良い事だと思うので、「作ったよ・やったよ」っていう事を
言うのが価値があるというのもある。
もしくは知らなかった人には当然価値のある新情報としてリーチすることができる、など良い面もあると思います。
要は誰向けに話すか、なんのために話すか、という事でどちらも正解なので難しい。


また今回は応募したトークの数もこれまで以上に多かったようですし、そのためにリジェクトされたものもあったようです。


そういう意味では、「世界最大規模のYAPC」では1対多の形式(セッショントーク形式)では話す方も聞く方も
嗜好とニーズが多様すぎるのではないか、という気がする。
多様さを許容するには並列数を上げる事になるけど、現状の3並列以上も現実的に厳しいだろうし。。


個人的にはトークでいうとlyokatoさんのが一番でしたが、「Perlあるある」のイベントが最も楽しかった。多対多のイベントをもっと多くして欲しいなという気がしました。
Perl入学式がどうだったのかは見られていないので、そこの成果も是非聞いてみたい
「2対多」の形式の「Mobile Application Development for Perl Mongers」も同じく聞けなかったのでわからないけど、
このような「(2|3|4|5...)対多」もっと言うと「多対多」のものがあっても良いと思う


「世界最大規模のYAPC」の魅力は著名な人から初めての人までが参加するイベントであることだと思います。
割と、「あの人最近来てないけどどうしてるんだろう」という事が少ない気がして、
YAPCに来ればあの人に会える」と思える事のが多いのも良い事だと思う。


まとめると、
・複数人で募集できるトーク(そういえば昔の miyagawaさんとtokuhiromさんの「Plack作ってる」のセッションは楽しかった)の仕組みはどうか
・スポンサーセッションを設けるとまたアレがソレかもしれないので、スポンサー企業のエンジニア同士でディスカッションすればスポンサー側も旨味があったりするのでは。「大規模トラフィックについて」というテーマだけでもそこそこのスポンサー企業の中の著名人引っ張ってこれるのでは。
・どうせ皆餃子食う(この響きも懐かしいけど)んだから、「適当に集まるスペースだけ作ればいいじゃん」というのはさすがにオーガナイズできないだろうし、成果も見えない(イベント行う上でこれも大事)ので言いません。
が今年の感想です。


などなど書きましたが、特に運営の皆様、今年のYAPCもお疲れさまでした。
上の感想は別として、また来年の開催を楽しみにしてます。