plenvsetup v0.06 has been released

Let’s setup your own perl environment without system-perl

Today I released plenvsetup v0.06. plenvsetup is a quick setup tool for perl environment with plenv. In the latest version, plenvsetup uses Shoichi Kaji(skaji)‘s perl-install instead of Perl-Build. This allows, we can install perl without system-perl under plenv. Now we can use new plenvsetup with following one-liner.
$ curl -sL https://is.gd/plenvsetup | bash
You may zsh instead of bash.

Build on a Docker container

plenvsetup works on a Docker container it based on latest alpine linux image too. For example, following Dockerfile setups the perl-5.30.0 with plenvsetup on container.
FROM alpine
WORKDIR /root

### install required dependencies (perl not required!)
RUN apk add bash libc-dev gcc make patch git curl

### download plenvsetup
RUN curl -sL https://is.gd/plenvsetup > plenvsetup && chmod +x plenvsetup

### use plenvsetup on bash
ENV SHELL=/bin/bash
RUN bash plenvsetup

### install perl-5.30.0 with plenv
RUN .plenv/bin/plenv install 5.30.0
RUN .plenv/bin/plenv global 5.30.0
RUN .plenv/bin/plenv rehash

CMD /bin/bash
Then, you can build the Dockerfile, and run perl-5.30.0 within the container.
$ docker build -t ytnobody/plenvsetup .
Sending build context to Docker daemon 2.048kB
Step 1/10 : FROM alpine
---> cc0abc535e36
Step 2/10 : WORKDIR /root
---> Using cache
---> 5a63e9728352
Step 3/10 : RUN apk add bash libc-dev gcc make patch git curl
---> Using cache
---> 0fed43f11239
Step 4/10 : RUN curl -sL https://is.gd/plenvsetup > plenvsetup && chmod +x plenvsetup
---> Using cache
---> 2b8ce1c5f1fa
Step 5/10 : ENV SHELL=/bin/bash
---> Using cache
---> 6f661e8cf191
Step 6/10 : RUN bash plenvsetup
---> Using cache
---> 24f2c6c713f0
Step 7/10 : RUN .plenv/bin/plenv install 5.30.0
---> Running in 86f08ede1c38
---> Downloading https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.30.0.tar.gz
---> Unpacking /root/.plenv/cache/perl-5.30.0.tar.gz
---> Applying Devel::PatchPerl 1.80 (patchperl-extracted 0.0.1)
---> Building perl 5.30.0
---> See /root/.plenv/build/1578556140.1/build.log for progress
---> ./Configure -des -Dprefix=/root/.plenv/versions/5.30.0 -Dscriptdir=/root/.plenv/versions/5.30.0/bin
---> make
---> make install
---> Successfully installed perl 5.30.0
Removing intermediate container 86f08ede1c38
---> 73c2b52fa025
Step 8/10 : RUN .plenv/bin/plenv global 5.30.0
---> Running in 439f41b196dd
Removing intermediate container 439f41b196dd
---> 8e819e1afd8c
Step 9/10 : RUN .plenv/bin/plenv rehash
---> Running in 31d3278595ce
Removing intermediate container 31d3278595ce
---> 28e28a126931
Step 10/10 : CMD /bin/bash
---> Running in c67a1e299db0
Removing intermediate container c67a1e299db0
---> 3ceac81cf2f4
Successfully built 3ceac81cf2f4
Successfully tagged ytnobody/plenvsetup:latest

$ docker run --rm -it ytnobody/plenvsetup
bash-5.0# perl -v
This is perl 5, version 30, subversion 0 (v5.30.0) built for x86_64-linux
(with 1 registered patch, see perl -V for more detail)
Copyright 1987-2019, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
So easy.

Kichijoji.pm #20 に参加しました

2019-11-22、六本木はフリークアウト社にてKichijoji.pm #20が開催されました。大変楽しませていただきました。7年目に突入ということで非常にめでたい節目でもあったようです。

なお私は途中からの参加となったのですが、懇親会LTにて「昔作ったソシャゲーの裏側」というタイトルで発表させていただきました。資料はこちら(PDF)

当日の様子についてはHaskell入門の著者であり熟練YAPCレポーターでもある@hiratara氏がまとめてくれています。

個人的に印象に残ったものとして、@818uuuさんの発表を挙げておきます。「人間が検索結果をどのように見ているのか」という研究の引用に「検索結果の見方は6種類に大別できて、それを共通アルゴリズムで説明できるのでは?」という話を聞いて、目からウロコでした。

さて、私の発表に登場した技術たちについて、如何せん古い内容でしたので、よくわからなかったという方もいらっしゃるかと思います。そこで、雑な内容ではありますが、このエントリで少し補足をしておきます。

Catalyst

Catalystは、2005年後半~2008年ころにかけて流行したPerlのWeb App Frameworkです。

現在でもメンテナンスが継続されており、ルーティングに独自のルールがあることが特徴の一つと言えるでしょう。

gearman

gearmanはPerl製のジョブシステムです。job clientからgearmandと呼ばれるデーモンにキューを渡すと、perlのwhileループを軸に組まれたworkerプロセスに対して処理を委譲することができます。

動作が軽量なのですが、workerプロセスがダウンした際、処理途中の内容が全部揮発してしまうのが難点でした。

TheSchwartz

TheSchwartzもPerl製のジョブシステムですが、その構成にMySQLが必要となり、ジョブそのものの堅牢性をMySQLに委ねることで、gearmanのような途中処理の揮発という問題が起こりづらいとされていました。

現在は@akiym氏によってメンテナンスされているようです。

UltraMonkey L7

UltraMonkey L7は、Linuxなどにインストールして利用するタイプの、オープンソースのソフトウェアロードバランサーです。

名前に含まれている通り、OSI参照レイヤのレイヤ7プロトコル(HTTPなど)に対するルールを設定できる、大変貴重なソフトウェアロードバランサとなります。

heartbeat

heartbeatは、Linux/HAプロジェクトの成果物の一つで、IPアドレスの冗長化構成を行うソフトウェアです。

これのおかげでロードバランサーやルータを多重化することができました。

iptables

Linuxカーネルに組み込まれたパケットフィルターです。よくある用途としてはファイアウォールとしての利用でしょうけど、最近ですとdockerが内部的にexposeのために利用しているようです。

Perlメインだった人からみたElixir

最近Elixirにふれる機会が有りましたので、理解を深めるためにも、見識を書いていきたいと思います。

なお、このエントリを書いている時点でElixir歴だいたい3日ほどです。いろいろ間違えているかもしれませんが、もし間違いに気づいた方、Twitterで教えてくれると嬉しいです。

私のメイン言語変遷

ここでいうメイン言語というのは、「業務で主に触っている(触っていた)言語」という定義でよろしくお願いします(他にもたくさん触ってますけど、かくの面倒なのでいろいろ端折ったりしてます)。

  • 1998: batch(MS-DOSのアレ)
  • 1999-2000: bash, batch
  • 2001-2002: bash, PHP, たまにPerl
  • 2003-2015: bash, Perl, たまにRuby
  • 2016-2018: JavaScript(Node.js), Swift, PHP, たまにPerl
  • 2019: JavaScript??

タイトルにPerlメインだった人って書いてるのは、多分自分で一番慣れている言語がPerlだからそうしている、という感じです。このエントリもPerl使ってる向けに書いているところがあるので、ご了承ください。

ちなみに、とってもお恥ずかしい話なんですけど、Elixirに触るまではElixirが動的型付け言語だということすら知りませんでした。

個人的感想「これPerlでは?」

少し触ってみて思ったのは、「これはRubyというよりPerlにだいぶ酷似してるな」ということでした。

Perlについては、比較的歴史のある動的型付け言語ということでよく知られているかと思います。そしてPerl自体はマルチパラダイムな言語なのですが、実はPerlのご先祖様はLispということもあって、関数型パラダイムの要素を多分に包含しているのです。

一方でElixirもまたマルチパラダイムな言語であり、関数型パラダイムの要素がふんだんに盛り込まれています。その上動的型付け言語だということになると、この時点でだいぶPerlに似ている感じがしますね。

Perlで言うところの「あれ」が「これ」

さて、ここからは具体的な例を挙げて、ElixirとPerlの機能ごとのマッピングを少しだけしていきたいと思います(並列性云々の話は、そこまでたどり着けていないので書きません)。

Cartonだとかcpmみたいなやつは「mix」

RubyでいうところのBundler、Node.jsでいうところのnpm、そしてPerlでいうところのCartonに相当するものとして、Elixirではmixというツールがあります。

このmixは、Perlでいうところの「Minilla」でもあります(パッケージ作成ツールです)。

例えばmy_modというパッケージを作成する場合は、mix new my_modを実行すれば、パッケージのひな形がmy_modフォルダに生成されます。このとき、assertionベースな検証手法が用いられたテストコードも同時に生成される点なんかは、minil newしたときとそっくりですね。

依存パッケージの指定は以下のように、mix.exsdefp deps doendの間につらつらと記入していくようです。

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end

そして依存パッケージの導入はmix deps.getだけでOKとなります。

metacpanみたいなやつは hex.pm

ドメインがまさかの.pmなのでElixirはPerl!!!」というのは冗談ですが、Perlで言うところのmetacpan.orgに相当するのがhex.pmというサイトになります。

hex.pmはもともとErlangとElixirのパッケージ検索サイトなのですが、ElixirがErlangのラッパー言語だからか、Erlangで使われているエコシステムをそのまま使ってるようです。

例えばhttpクライアントが欲しい場合、hex.pmでhttp clientを検索すれば、いくつも該当します。

ただ、hex.pmにおける各パッケージのドキュメンテーションは、そのスタイルが統一されていない(CSSが全く違うというレベル)ので、読む側としては正直なんとかしてほしい気持ちはあります。きっとルールが定められていないからなんでしょうかね。。。

REPL(PerlでいうところのReply)は「iex」

標準でついてくるREPLはiexというものでして、必要十分かつ標準的な機能を持ちます。Perlで言うならばReplyが似たようなものかと思います(コチラは標準ではついてこないですが)。

Sigilは意味が違うけど、Perlにあるアレと似てる

Perlでは、Sigilというと変数の最初につく$@といった「変数の性質を決める記号」という事になっていますが、Elixirでは異なる意味の物となっています。それは、以下のような文字列リテラルや正規表現、文字のリストなどを表すためのものです。

// 文字列リテラル(エスケープ・式埋め込みあり)
strX = ~c/1 + 2 = #{1 + 2}/

// 文字列リテラル(エスケープ・式埋め込みなし)
strY = ~C/1 + 2 = #{1 + 2}/

// 正規表現
regex = ~r/(Perl|Elixir)/i

これらをiexで出力してみると、以下のような結果になります(IO.putsはperlで言うところのsayみたいなやつ)。

iex> strX |> IO.puts
1 + 2 = 3
:ok

iex> strY |> IO.puts
1 + 2 = #{1 + 2}
:ok

iex> "I like Elixir" =~ regex  
true

iex> "I like PHP" =~ regex   
false

iex> "I like Perl" =~ regex
true

正規表現の適用が=~なのもPerlと全く同じで、親しみすら感じます。

ところで、ElixirのSigilに相当するものが「演算子」という形でPerlにもあって、以下のように利用できます。

# 文字列リテラル(Elixirの~cに近いが、変数展開はするけど式展開はだいぶ特殊)
my $strX = qq/1 + 2 = @{[1 + 2]}/;

# 文字列リテラル(Elixirの~Cに同じ)
my $strY = q/1 + 2 = @{[1 + 2]}/;

# 正規表現
my $regex = qr/(Perl|Elixir)/i;

これらをsayしてみると、以下のような結果になります。

# 実行内容
use feature qw/say/;
my $strX = qq/1 + 2 = @{[1 + 2]}/;
my $strY = q/1 + 2 = @{[1 + 2]}/;
my $regex = qr/(Perl|Elixir)/i;
say $strX;
say $strY;
say 'I like Perl' =~ $regex;
say 'I like PHP' =~ $regex;
say 'I like Elixir' =~ $regex;
# 実行結果
1 + 2 = 3
1 + 2 = @{[1 + 2]}
Perl

Elixir

まとめ

ElixirとPerlの似たところをほんの少しだけ取り上げてみました。これをきっかけに、ElixirもPerlもちょっとでいいから利用者増えてほしいなぁ・・・

実は他にも似ている箇所が結構ある(構造体とパッケージの紐づけとか)のですが、このエントリはここまでにしたいと思います。この2つの言語、だいぶ似てませんか?私はかなり似ているなと思うんですが・・・。

フリーランスになりました

副業から本業に

もともと副業といいますか個人事業を一昨年からやっていて、これまでもいくつかチームマネジメントや技術相談などをご用命いただいていましたが、本日より完全にフリーランスとなりました。

ともあれ、これまで私を正社員として雇ってくださった会社とは、引き続き業務委託という形で(稼働日数を減らして)一緒にお仕事を続けることになっています。

動機

ちょっとした野望を内に秘めているのですが(いまはまだ明かせません・・・)、これを実現するためには、若干自分の時間が足りないな、と半年ほど前から実感していました。しかし、副業をしていたこともあり、稼ぎについて大きな不安なしにこの決断をすることができました。

この結果を得るまでにはそこそこの紆余曲折を経ましたが、とにかく、時間の使い方をもうすこし自分で選びたい、という小さな目標はこれで達成できるのかなと思っています。

どんなお仕事をやっていくのか

冒頭でリンクしたスイ・ソリューションズ(屋号)では、主に以下のようなお仕事を承っております。

  • 各種システムの現状調査
  • webシステム及びクラウドシステムに関するアドバイス・提案

ちなみに今年でITエンジニアとしてのキャリアは20年目に突入するのですが、私は下記の事項に実績があります。

  • Microsoft Azureにおける各種SaaS/PaaSを使ったシステム設計・構築・運用(特にAzure Functions)
  • 20年にわたるLinuxに関する知見
  • Perl, PHP, bash, JavaScript(Node.js), Swiftなど、10種以上の言語による開発実績(とくにAPI)
  • TDDの導入
  • MySQLにおけるクエリチューニング(あくまで開発者として。)
  • エンジニアチームの立ち上げ、マネジメント、メンタリング
  • プロジェクトのマネジメント
  • 事業におけるシステムのポジション定義と予算策定

もし興味がありましたら、メールやTwitterでご連絡ください。無論、対面でも構いません。

まとめ

装甲騎兵ボトムズ的にまとめるなら、以下のようになるところでしょうか。

変わる、変わる、変わる。この世の舞台をまわす巨獣が、クラウドの底でまた動きはじめた。

天が軋み、人々は呻く。舞台が回れば吹く風も変わる。
昨日も、今日も、明日も、時の流れに閉ざされて見えない。

だからこそ、時を操る術を求めて、褪せぬ技術を信じて求めて。

次回「急変」。

変わらぬ技術などあるのか。

WEB+DB PRESS Vol.109 に寄稿させていただきました

紹介

WEB+DB PRESSVol.109(技術評論社:gihyoより2月23日発売予定)のPerl Hackers HubコーナーにサーバレスでもPerlというテーマで寄稿させていただきました。

ぜひお買い求めください!

Perl Hackers Hub – Perl Hacker達による旬の技術の紹介

Perl Hackers HubとはWEB+DB PRESS誌内の連載のひとつであり、Perl Hacker自身が筆を執り旬の技術を紹介するというものです。

gihyoさんのPerl Hackers Hubのページには、Perl Hackers Hubについて以下のような説明がついています。

本連載は,第一線のPerlハッカーが回替わりで,Perlの旬な技術について解説していきます。

記事概要

Microsoft Azure Functionsを使ってPerlスクリプトを実行します。スクリプトの内容は、「画像URLを与えると、画像の顔認識結果(年齢と性別)をJSON形式で返すWeb API」です。

サンプルコードとして、Azure上に環境とプログラムを全自動でデプロイしてくれるスクリプトを収録してあります。Azureアカウントがあれば、最初の無料枠で試せる範囲の内容となりますので、ぜひともお試しください。

謝辞

この度機会を与えてくださった@songmuさん、Perl Hackers Hubコアメンバーの皆さん、そして一緒に原稿の仕上げをしていただいた@inaoさん、本当にありがとうございました。

特に@inaoさんには度々ご迷惑を掛けてしまったにもかかわらず、辛抱強く対応してくださいました。感謝しきりです。

また、Azureについて深く言及した内容の記事はWEB+DB PRESS誌上では初めてだそうです(本当ですか?)。私も驚きました。正直な話、流石にAzureについては過去に誰か書いているだろうと思っていたのですが…意外なところで「誌上初」だったんですね。

ともかく私としては、今回の記事がPerl Hackers Hubというコーナーを通じて、様々な技術に触れるきっかけを読者の皆様に作ることができたらいいな、と思っています。

YAPC::tokyo 2019で登壇しました

YAPC::Japan 2019にて「実演サーバレスPerl – 顔認識データを扱おう」というタイトルで登壇させていただきました。見に来てくれた方、本当にありがとうございます。

そして、結局ライブコーディングするための時間が足りず、見せ場を作れなかった点、本当にごめんなさい。あの後、見に来てくれていた同僚や@note103さんに励まされたのが本当にありがたかったです。

資料

敗因

20分で、受け手側に前知識が必要な内容をライブコーディングするのは、あまりにも無謀でした。

前知識のインストールが終わった時点で7分ほど経過しておりました。さらにクラウド側(Azure)の処理待ち時間が思った以上にかかる。

これではまずいということで、事前に用意しておいた出来上がり環境を使って説明していきましたが、それでも時間が足りず、コードを書くところをお見せできませんでした(コードそのものをお見せすることはできたのですが・・・)。

補足(というか宣伝)

今回のセッションをおさらいする内容で、Web+DB Press誌 2019年2月号のPerl Hackers Hubに寄稿させていただいております。まだ発売まで時間がありますが、より詳しく解説されているものとなりますので、興味のある方はぜひお買い求めください!

また、Web+DB Press誌ではサンプルコードも提供します。サンプルコードは、今回の顔認識システムを自動でAzure上に構築するスクリプトとなっておりますので、構築する手間が惜しいが試すだけ試してみたい、という方にもおすすめです。

前夜祭でもLTしました

本編のみ参加の方はご存じないかもしれませんが、前夜祭でもLTで発表しました。Webappにおける@INC Hooks絶対許せないマンとしてネタに振り切った内容です。

LT資料

Acme::AtIncPoliceのその後

実は昨日Acme::AtIncPoliceissueが立ちまして。なんだろうと思ってみてみると、「Testで使ってるTest::Exceptionが入ってないからTest失敗するんですが」という内容でした。

それを受け、今朝慌ててTest::Exceptionをdependencyとして登録し、shipit。なんと0.01をshipitしてから、たった2日で0.02をshipitすることとなってしまいました・・・

感想など

@songmuさんベストトークおめでとうございます!感極まって感情が溢れ出たときに、周りで何名かもらい泣きした人がいたんですが、songmuさんの情熱があるからこそなんだろうなと。

個人的には@risouさんのPerl6トークと@hitode909さんのWebVRトークがかなり良い話だと思いました。hitode909さんからは豆本の夢日記を頒布していただきました。家宝にします。

Azure Functions v1 + Node.jsなアプリケーションをAzure Functions v2に移行してみる話

このエントリはServerless2 Advent Calendar 2018の17日目のエントリとなります。

半月ほど前業務で、稼働中のAzure Functions v1 + Node.jsなアプリケーションをAzure Functions v2に移行する作業を行いました。

その際、今後も似たような移行作業があり得そうだと考え、この作業をざっくりこなしてくれるスクリプトを作りました。それがytnobody/azure-func-migrate-nodeです。ちなみにPerl製ではなくNode.js製です。

如何せんやっつけで作ったスクリプトですので、漏れ・抜けなどはあるかもしれませんが、お手すきの際にでもpull-reqしてくださると幸甚です。

移行のために最低限必要な処理

大きく分けて、以下の作業が必要となります

  • bindingsに対応したextensionsをインストールする
  • ランタイムバージョンを2.0に設定する

bindingsに対応したextensionsをインストールする

実際のextensionsインストール作業はfunc extensions installに委譲しているのですが、これまでv1で使っていたbindingsに相対するv2 extensionsを検出するロジックは作成しました。

なお、v1では"type": "documntDB"と指定していた箇所は"type": "cosmosDB"に変更する必要がありますので、その対応も行っています。

ランタイムバージョンを2.0に設定する

これもロジックを作りました。

まとめ

ざっくりと移行スクリプトを作りましたので、公開しました。が、だいぶやっつけで作ってありますので、適宜pull-reqをしてくださると幸甚です。

昔書いたGithub止まりのモジュールをほじくり返す – Test::Proc 篇

※このエントリはPerlアドベントカレンダー2018の5日目のエントリとなります。

CPAN(MetaCPAN)でモジュールを公開するということ

Perlでプログラムを書くことに慣れてくると、CPANモジュールを使うようになったり、もっと慣れてくると自分でPerlモジュールを作るようになり、最終的にはCPAN(今はMetaCPANですね)で公開するようになるかもしれません。私は過去にそのような道を歩んできました。

では私は過去にどんなモジュールを書いたのか。ひとまずMetaCPANに上がっているものを一部挙げると、 Otogiri(これはほとんど@tsucchiさんの力です), XML::Diver, Net::Azure::CognitiveService::Faceなどがあります。

PerlモジュールをMetaCPANで公開する前に

しかしながら、MetaCPANでモジュールを公開する前に気にかけておいて欲しいこととして、個人的には以下のような項目を挙げたいと思います。

  • そのモジュールを公開することで不快感を感じる人々が生じないか
  • そのモジュールはセキュリティ的に致命的な問題を抱えていないか
  • そのモジュールは新しい機能を提供してくれるか
  • そのモジュールはプログラミング体験をより幸せにしてくれるか
  • そのモジュールは従来の類似モジュールよりもパフォーマンスに優れるか
  • そのモジュールは従来の類似モジュールよりも依存性が削減されているか

もし上記について該当するかわからない場合は、ひとまずgithubに上げておきつつ、ブログやTwitter等で言及してみましょう。運が良ければ誰かが注目してくれて、レビューをしてくれるかもしれません。これらのことは、Perlモジュールの公開に及び腰になってしまわない程度に、気をつけるとよいのではないでしょうか。

CPANの歴史を少しだけ垣間見る

では、なぜこのように自律する必要があるのでしょうか。それを知るためには過去に目を向けることが重要です。

歴史を振り返ると、charsbarさんによるエントリでCPANは幼稚園児の砂場じゃないよねという、2008年当時、大変考えさせられたものがあります。若い方の中にはこのような歴史を知らない方もいると思いますが、是非とも同じ轍を踏まぬための知識として、知っておいていただければ幸いです。

また、まかまかさんによるPerl同人誌「Acme大全」には、「Acme大全2012」から毎回、巻末付録として「とあるAcmeモジュールの削除について」という章が設けられています(ブログにも同様のエントリがある)。

このように、MetaCPANへモジュールを公開する上では、ある程度その性質を律せられる側面があることは間違いないでしょうし、誰かがつらい思いをしないためにも必要なことであると私は思います。

それでも日の目を見ないモジュールもある

そんな事もあって、実際にはたくさんのPerlモジュールを作っていたとしても、実際にMetaCPANにて公開されるものはその一部でしかありません。ほかにもMetaCPANに公開するのが怖いとか、作者がそこまでの有用性を感じていないだとか、謙遜している、などの理由でMetaCPANで公開されていないPerlモジュールがGithubにはあります。

このようにあえてGithubでの公開にとどめられているPerlモジュールを、私は親しみを込めてGithub止まりモジュールと呼んでいます。

そして今回紹介するGithub止まりモジュールは、拙作のTest::Procです。

Test::Proc – プロセスを起動し、その起動状態をテストする

Test::Procは5年前にGithubにpushされています。今となっては当時の記憶を頼りに解説する他ないという点がいささか不安です。

さて、Test::Procが目指したところは、テストスクリプトでプロセスの起動状態をテストしたいというものでした。

使い方はSYNOPSISにある通りです。(done_testingが抜けていたので、補足してあります。)

use Test::More;
use Test::Proc;


my $proc = test_proc 'my_task' => sub {
    print 'test';
    warn 'dummy';
    sleep 20;
};


$proc->is_work;


$proc->stdout_like( qr/\Atest/ );
$proc->stderr_like( qr/\Adummy/ );


$proc->exit_ok;
done_testing;

あら捜し

レポジトリを見てみると、テストの少なさが気になります。github止まりモジュールにはよくある話かもしれないですが、だいぶ控えめなテストの数だなと感じますね。

そしてインターフェースが片手落ちです。というのも、このTest::Procはtest_procというDSLを提供しており、Test::Proc::Objectインスタンスを返しているのですが、test_proc側にはクロージャ以外でプログラムを起動する方法が提供されていません。Test::Proc::ObjectはProc::Simpleのサブクラスであり、24行目で引数の$codeを実行しているので、Proc::Simpleのインターフェースを見る限り、文字列で外部コマンドとオプションを渡すことができるはずです。

実験

実際に以下のようなテストを作って実験してみました。

$ cat hoge.sh 
sleep 3
echo "hoge"

$ cat t/12_shell.t 
use strict;
use Test::More;
use Test::Proc::Object;

my $proc = Test::Proc::Object->new('sleep 3 sec. Then print "done"', 'bash ./hoge.sh');

$proc->is_work;
$proc->exit_ok;
$proc->isnt_work;

$proc->stdout_like(qr/\Adone\z/);
$proc->stderr_like(qr/\A\z/);

done_testing;

これを実行すると、以下のようになり、テストは成功します。

$ perl -Ilib t/12_shell.t 
ok 1 - process sleep 3 sec. Then print "done" is work
ok 2 - process sleep 3 sec. Then print "done" exit code is 0
ok 3 - process sleep 3 sec. Then print "done" is not work
ok 4
ok 5 - process sleep 3 sec. Then print "done" STDERR like (?^:\A\z)
1..5

深掘りしていく

上記のことから、test_procにコマンドを文字列渡しして起動させることができそうですが、実際に以下のようなテストを試してみると、失敗してしまいます。

$ cat t/13_shell-with-test_proc.t 
use strict;
use Test::More;
use Test::Proc;

my $proc = test_proc 'my_work' => 'bash ./hoge.sh';

$proc->is_work;
$proc->exit_ok;
$proc->isnt_work;

$proc->stdout_like(qr/\Adone\z/);
$proc->stderr_like(qr/\A\z/);

done_testing;

$ perl -Ilib t/13_shell-with-test_proc.t 
Type of arg 2 to Test::Proc::test_proc must be sub {} (not constant item) at t/13_shell-with-test_proc.t line 5, near "'bash ./hoge.sh';"
Execution of t/13_shell-with-test_proc.t aborted due to compilation errors.

これはtest_procのインターフェースが($&)となっているために起こっている問題となります。ですのでこれを($$)としてあげると、以下のように成功します。

$ perl -Ilib t/13_shell-with-test_proc.t 
ok 1 - process my_work is work
ok 2 - process my_work exit code is 0
ok 3 - process my_work is not work
ok 4
ok 5 - process my_work STDERR like (?^:\A\z)
1..5

なぜgithub止まりなのか

このように、完成度の低さゆえにgithub止まりとなっているTest::Procですが、その他に大きな理由として、私個人が出くわす状況にそもそもテストスクリプトでプロセスの起動状態をテストしたいケースがあまりにも少ないという点が挙げられます。

そういうわけで、結局あまり洗練もされないまま5年もgithub止まりとして塩漬けになっていたというわけです。

Test::Procの今後

一応、ユースケース的に「いいじゃん?」って思ってくれる人がいらっしゃるのであれば、forkしてshipitするまでやってくだされば良いとおもいますが、今の所私自身がなにかをするということは無いでしょう。

コンセプトモデルということでここはひとつ、ご理解いただければ幸いです。

まとめ

ざっくりまとめると以下のようになります。

  • MetaCPANでPerlモジュールを公開する前に、いま一度そのモジュールの性質を見つめ直そう
  • Perlコミュニティの歴史から、誰かがつらい思いをしないための行いについて知ろう
  • Test::ProcというPerlモジュールを作ったけど、ユースケースに遭遇しなさすぎて結局Github止まりになった
  • Github止まりモジュールは「コンセプトモデル」として見ると良さそうかも

明日のPerlアドベントカレンダーは6日目。@yoku0825さんによる「マイエスキューエルにはPerl Mongerが必要かもしれないはなし」です。

Twitterアカウントを凍結されてしまいました。

しばらくはこちらのサブアカウント にて細々とつぶやいております。

ちなみに本日は私の誕生日でした。最高のプレゼントをありがとう、Twitter!

状況

Azure関連でちょっとした疑問があったので、 @AzureSupport に質問をしたところ、

と言われました。

言われたとおりに質問内容と、サポートに必要なID情報をDirect Messeageにて伝えたところ、suspendedとなってしまいました。

見解

今回suspendedとなってしまった原因は “Violating our rules against evading permanent suspension.” だそうです。

原因については「なるほど?」という感じですが、そもそも今回の経緯から、Twitter社はDirect Messageを覗き見しているという事がわかりました(利用規約にはその旨が書かれている)。

おそらくコンテキスト等を無視して、固有情報らしきものが流れてきたら簡単なチェックを経て、必要に応じてsuspendしているのではないでしょうか。

今後

不服申立てはすぐに行いました。が、仮にアカウントが復活しても、あまりアクティブな利用を行わず、そのままmastodonあたりに流れるかもしれません。

翌日

アカウントの解凍が行われました。Twitter社の担当部門の皆様、大変お手数をおかけしました。

Twitter社においては、認証済みアカウントとのやり取りにおける秘匿情報の取扱いについて、検閲・凍結のルールを見直していただくことを願う次第です。

200ミリ秒の検索APIをMicrosoft Azureでデザインする

200ミリ秒の検索APIとは

ここでは、httpクライアントからリクエストを受けてから全文検索を含む何らかの検索処理を行い、httpクライアントにレスポンスを返すまでの処理を、おおむね200ミリ秒(200ms、0.2秒)前後の時間でこなすWeb APIを指します。

検索という機能を考えたとき、200msという数字はまずまず軽快な応答速度ではないかと私は考えます。

今回はAzureの各種サービスを使って検索APIを作った時のノウハウを共有します。このAPIはデータサイズによって多少のばらつきはあるものの、ほぼ200ms前後の応答速度を実現することができております。

以下は、実際の処理履歴となります。おおむね200ms前後で処理が完了し、応答していることが分かると思います。

Microsoft Azureで作る

Microsoft Azure(以下Azure)で検索APIを作るにあたり、以下のようなシステムデザインを行いました。

ある程度Azureに詳しい方であれば、上記の図を見ただけで概ねの構成がご理解いただけると思います。

Azure CDN

いわゆるCDN(Contents Delivery Network)サービスです。今年から動的コンテンツの高速化にも利用できるようになりました。

今回のケースでも「動的コンテンツの高速化」がその利用目的となります。

Azure Functions

実際にhttpリクエストを受け付け、httpレスポンスを返すためのアプリケーション・ロジックをデプロイし、運用するためのFaaSとなります。最近v2がリリースされましたが、私のケースではv1を利用しました。

C#やF#、PHPなどの言語に対応していますが、今回はNode.jsをつかって作ってみました。実際の実装・はまりどころについては前回のエントリにまとめてありますので、そちらも併せてご参照ください。

Azure Search

Apache LuceneクエリやODataフィルタを利用可能な検索エンジンサービスです。

全文検索や緯度経度をもとにした距離検索、ファセットなどにも対応しているため、複雑な検索機能を実装するにはほぼ必須となります。

また、Azure CosmosDBやAzure Table Storageなどから定期的(最短で5分おき)にデータを取り込むIndexerという仕組みがついてきますので、検索結果にリアルタイム性を求めない限り、データのインポートをする仕組みを自分で作る必要がありません。

Azure CosmosDB (または Azure Table Storage)

どちらもスキーマレスなデータストアとして利用できるサービスです。

今回はAzure CosmosDBを利用し、Azure Search向けの一次データをストックしておくデータストアとします。

まとめ

200ms前後の応答速度の検索APIをAzureで実現するシステムデザインを紹介しました。

「えっ、実際の作り方は書かないの?」という声が聞こえてきそうですが、その辺は公式ドキュメントや有志のブログに書いてあることしかやっていません。

強いてあげるとすれば、前回のエントリで書いたようなはまりどころがあるくらいですので、そちらを見ていただきたいと思います。

参考にしたドキュメント・ブログ