今回はそんなうちの子が産まれたときに取得した育休の話をしたいと思います。育休の話とはいっても育休をハックする話とか育児アプリとかの話ではなく、「育休を取得しやすい(と私は思う)SPEEDA開発チームの環境」についての話をします。本編がそこそこ長い(スミマセン)ので前置きはここら辺で切り上げることとします。男性の育休取得率さて突然ですが、2018年度の日本における男性の育休取得率がどのくらいかご存知でしょうか?6.16%です。これは過去最高の取得率だそうです。ちなみに同年の女性の育休取得率が82.2%だそうなので、過去最高とはいえども残念ながらまだまだ低い数値といえるのではないでしょうか。このような状況の育休ですが、SPEEDA開発チームでは昨年私を含めた2人が育休を取得しています。母数が少ないので一概に「育休取得率が高い」とは言えないですが、間違いなく育休を取得しやすい環境であると思いますし、だからこそ私は育休を取得したので、今回は私たちの環境の紹介を兼ねて次のような話をしようと思います。SPEEDA開発チームにおいてはどうしているか男性が育休を取らなかった理由では、まず一般的にどういう理由で育休が取られていないのか、2018年度のデータを見てみましょう。育休を取得しなかった理由2018これを見ると、男性が一体どういう理由で育休を取得しなかったかがわかります。三菱UFJリサーチ&コンサルティング「平成29年度仕事と育児の両立に関する実態把握のための調査研究事業」)Top3はこのようになっています。自分にしかできない仕事や担当している仕事があった(22.1%)今回はこのうち2位の「職場が育児休業を取得しづらい雰囲気だった」と3位の「自分にしかできない仕事や担当している仕事があった」にフォーカスして話を展開したいと思います(人手不足の話は採用や業務効率化に絡んだ話だと思いますが、そこについては別軸の問題だと思いますので今回は言及しません)。育休を取らなかった理由の原因を考えてみる次に、上記2つの理由について私なりに原因を考えてみたいと思います。職場が育休を取得しづらい雰囲気になっている原因なぜ育休を取得しづらい雰囲気になってしまっているのでしょうか。原因を私なりに考えてみましたが、このようなことが考えられるのではないかと思います。1.普通の休暇すら取りづらい普通に1日2日の休暇を取ることが難しい環境の場合、ある程度まとまった期間になるであろう育休は余計取りづらく感じることかと思います。いう場合に休暇が取りづらくなるのか、2つ思い当たります。1つ目は、自分が担当している仕事に期限があり、休むことで間に合わなくなったり、後々辛くなったりと自分が困るケースです。2つ目は、自分が休むと自分の仕事を周囲の誰かが余分に担当することになり、迷惑がかかるケースです。1つ目のケースで休んだ分を自分でカバーできずに間に合わなくなった場合は、2つ目のように他の誰かがフォローにまわり結局周囲の負荷が増えることが考えられます。いうことを考えていくとやはり休みづらくなるのではないでしょうか。いった懸念は想像に過ぎず実際は自分が休んだところで大した迷惑はかからないのかもしれませんが「安心して休める仕組み」が整っていなければ心理的に休みが取りづらいということはあるでしょう。2.周りの人が普通の休暇すら取らない自分だけではなく、周りの人も「1」と同じように自分が困ったり、周囲への迷惑を気にして休みを取得しないような環境では休みづらくなるかと思います。お互いをお互いで縛り合っている感じです。同調バイアスによる負の連鎖と言えるかもしれません。休暇と同様に、子供が産まれたのに誰も育休を取得しないような環境では遠慮してしまう(遠慮しなければならない気持ちになる)のではないでしょうか。3.男性の育休に理解がない周りの人たちが男性の育休に対して理解がない場合、育休は取得しづらい雰囲気になるでしょう。すれば育休を取得しやすい環境になるか私が挙げた原因はどれも環境が原因となっていますが、どうしたら育休を取得しやすい雰囲気を作れるでしょうか。「1」は色々な解決方法があるでしょうが、上述のとおり休んだ場合に自分を含めて誰も困らないような「安心して休める仕組み」があれば解決しそうです。「2」の解決には「1」の仕組みの存在に加えて実際その仕組みが働いている必要があります。「3」は「1」の仕組みで部分的に解決しそうです。「3」のような人たちが育休に反対する理由は”育休を取得することによって自分や他の人たちに迷惑がかかる”ということにあったりするからです。「誰かが迷惑するから育休には反対」とは言えても「誰にも迷惑はかからないが育休には反対」とは言えないのではないでしょうか。「安心して休める仕組み」が存在して運用されていることが、育休を取得しづらい雰囲気を解消する方法の一つになりそうです。安心して休める仕組みとは休みを取得しづらい理由として「休むと自分が困る」というものがありました。自分が休むと困る状況になっているのでしょうか。それは「仕事が個人に対してアサインされている」からではないでしょうか。そもそも自分がやらないといけない仕事なので、誰かに代わってもらいづらいというわけです。このような環境では他の人も同様に「自分の仕事」をもっているでしょうから。「仕事がチーム対してアサインされている」ならば問題はないのでしょうか。チームで仕事をしていても、仕事が属人化しないようにしないと今回の文脈では結局困ることになります。仕事が属人化していると、計画的に休む場合は引き継ぎが発生するでしょうし、突発的に休むなら引き継げない分を自力で調査したりする手間が発生するからです。「仕事がチームに対してアサイン」されており、属人化も防がれていなければなりません。SPEEDAの開発チームではどうしているかSPEEDAの開発チームでは基本的に「仕事はチームに対してアサイン」されます。「ペアプロ」が属人化を防ぐのに役立っています(やっと本題!)。(属人化を防ぐためだけにペアプロをしているわけではないことを補足しておきます。ペアプロには属人化の軽減以外にも沢山のメリットがあるんです。今回の話では「属人化」の観点にフォーカスします。)ペアプロについて具体的にSPEEDAの開発チームは、すべてのチームがほぼ100%ペアプロで作業しています(ペアプロそのものについての詳しい説明は割愛させていただきます)。プログラミング以外(例えば採用活動)でもペア作業をします。ペアを組むメンバーを一日のうち何度も入れ替えており、様々なメンバーと様々な開発ストーリーに取り組むことになります。領域もUI/UX含めたフロント周りから、バックエンド、インフラ、CI/CDなどすべてを皆で担当します。その結果として、チームの中で「フロント部分はAさんしか知らない」「バックエンド部分はBさんしか知らない」という属人化が起きなくなっています。チームの人数が多く、かつ小規模なストーリーの場合、自分が担当する前にストーリーが終わってたということはありますが、自分しか知らないという状況にはなりません。チームの人数が奇数の場合は一人作業※が発生しますが、その場合は一人でも十分なストーリーを選ぶような工夫をしています。※一人で作業するというのは普通かもしれませんが私たちの場合ペアが基本なため一人は特別な感じです。そのため、誰かが休んで困るということが基本的にありません。用事があれば休みますし、周りがそうなので上述のように「周りが休まないから休みづらい」ということがありません。ペア作業のイメージここで補足としてペア作業についてイメージしやすいように絵で表してみることにします。あるチームにメンバーとして、Aさん、Bさん、Cさん、Dさんがいるとします。ペアは、AさんとBさん、CさんとDさんという組み合わせとします。環境はこのような感じです。一つのデスクトップPCにモニター2つとキーボード2つが接続されています。マウスが見当たらないのは画像の手抜きではなく、Thinkpadのトラックポイント付きキーボードを使っているためです。各々に対してキーボードが存在するため、ドライバーとナビゲーターの役割がスムーズに交代できます(キーボードが一つしかなかったら、心理的にキーボードを渡してもらったり渡したりというのがやりづらくなるかと思います)。モニターはミラーリングされていたり左右で分割されていたり、ペアによってやりやすいように変えています。CさんDさんペアも同じ構成で作業します。作業の流れ時間は13時、AさんとBさんペアはストーリーXに着手します。CさんとDさんペアはストーリーYに着手します。時間が14時になりました。ここでペアを入れ替えます。1コマの時間(ペア交代までの時間)は、チームで話し合って決めます。この例では1時間で交代するものとします。今度はDさんAさんペア、BさんCさんがペアになりました。横にスライドする形ですね。入れ替えの際は、作業開始時にいまどういう状況なのかの共有が行われることが多いです。(省いていますが、本当は適宜休憩を入れます(休憩超大事!))また、OSやディレクトリ構成などは意図的に統一しているため、別のマシンに使ったとき困りません。時間が15時になりました。CさんDさんペアと、AさんBさんペアです。これで全員がストーリーX、ストーリーY両方に少しずつ関わったことになり、特定のメンバーしかわからないということがなくなりました。複数のストーリーに少しずつ関わるということは、一つのストーリーに100%関われないことも同時に意味し、自分の知らないコードが存在し得るようになります。いった問題に対しては、他のメンバーに伝えた方がよさそうなことについて(例えば設計の部分)は都度々々共有したり相談したりしながら進めることで対応しています。メンバーが増えていくとこういった共有も大変になってきたり、上記のペアの入れ替え方法だとペアを組めない人たち(例えばAさんとCさんはペアになれない)が出てきたりと、ペア作業については話題が尽きないのですが、今回の趣旨はペア作業によって属人化が軽減されているということであるため割愛させていただきます。チームの入れ替えチーム内でペアの入れ替えを行っていることは上述しましたが、チームをまたいだメンバーの入れ替えも行われています。XチームとYチームという2つのチームがあったとします。このチームに対し、それぞれが担当している仕事はそのままに、メンバーを一部入れ替えるのです。↑を↓のように入れ替える。入れ替えの頻度は決まっておらず、リソース調整の結果であったり、タイミング的なものであったりします。基本的には本人の意思が最大限に尊重され本人が希望するチームに移動することになります。強い理由があって同じチームに長く残るということもあります。このような入れ替えが行われることにより、SPEEDAの開発チームにおける属人性は極めて少なくなっているといってもよいかと思います。※ペアプロと同様に属人化を防ぐためだけに入れ替えをしているわけではなく、知見の共有であったりチームに新たな風を起こしたりと他にも色々メリットがあるから入れ替えが行われています。最後に私がSPEEDA開発チームにおいて、育休を取得しづらいとは思わなかった理由は、ユーザベースという会社自体も周りの人たちも男性の育休に理解があったということもありますが、ペアプロとチームの入れ替えによって「属人化」が軽減されており「自分が休むと誰かが困る」という心理的負担がなかったことも大きいと思います。今回は主に「属人化」という点にフォーカスしてペアプロの話をしましたが、ペアプロがもたらす良い作用は他にも沢山あるので、(いきなりは難しいかもしれませんが)興味がわいた方は是非ペアプロを取り入れてみてはいかがでしょうか。なく、小規模に始めたり、短時間やってみたりするだけでも「良さ」がわかるかもしれません。19:00ペアプロと育休の取得しやすさの関係についてTweetもっと読むコメントを書く2019-10-07Ringアプリケーションで例外をいい感じにハンドリングする方法(Ductでの解説も含む)Tweetこんにちは!こんにちは!SPEEDA開発チームのあやぴーです。社内のClojureを使ったAPIにおいて、「例外をうまくハンドリングしたいんだけど...」という話が出てきたので、今回はRingアプリケーションにおける例外のハンドリング方法について解説します。昨今Ductを使ってアプリケーションを作る機会が増えているので、それについては最後の方に解説をします。具体的なコードはGitHubにあるので、参考にしてみてください。https://github.com/ayato-p/exception-handlingこの記事で解説する具体的な内容については以下の通り例外のハンドリングにRingミドルウェアを使う例外によってレスポンスを変更するDuctアプリケーションへの適用方法まとめ例外のハンドリングにRingミドルウェアを使うRingアプリケーションの特にRingハンドラー(以下、ハンドラー)部分で例外が出る場合について考えてみます。簡単のために以下のように、例外を投げる処理do-somethingを実行するハンドラーthrow-exception-handlerがあることにします。res)))本来であればdo-somethingが適当な値を返して、それをハンドラーのレスポンスとして返すところですが、この例ではdo-somethingが例外を起こすため、適切なレスポンスを返すことができません(Ringアダプターの実装にもよりますが、多くの場合は500エラーが返ると思います)。このハンドラーの挙動は以下のテストで確認することができます。data))))))このようにハンドラーの中で例外が発生する場合、各ハンドラーやその手前のレイヤーで適切にハンドリングして、例外をハンドラーの外側に伝播させないというのも場合によってはやると思います。予期しない例外や一般的な例外などに対してすべてのハンドラーで対応するのはあまりにも面倒です。いった例外をハンドルするための、いい感じの機能が欲しいところです。Javaの場合、JAX-RSのExceptionMapperあたりが今回欲しい機能に該当しそうです。Ringには残念ながら同じようなものはありません。そのため、少しだけ考えてみることにします。上記のテストコードがヒントになりそうです。上のコードのようにthrow-exception-handlerにリクエストマップを渡すようなコードをtry~catchで囲んで、例外を吐き出したときのみ例外のレスポンスマップを返すように書くことを考えれないでしょうか。500))))このようにハンドラーを実行して、その結果次第でレスポンスに影響を与える方法を僕らは既に知っているはずです。Ringミドルウェア(以下、ミドルウェア)です。次のようなミドルウェアwrap-exception-handlerを考えてみます。500))))))これはハンドラーを受け取って、新しいハンドラーを返します。新しいハンドラーは元のハンドラーに対して、自身が受け取ったリクエストを適用するだけで基本的には何もしませんが、例外が投げられたときにそれをキャッチして500のステータスコードを返すようにしています。wrap-exception-handlerは以下のテストコードで機能していることを確認することができます。req))))))例外によってレスポンスを変更する例外をハンドルすることができたので、今度は例外の種類によって返すレスポンスを変化させてみます。想像がついていると思いますが、try~catchで掴む例外を複数用意すれば簡単にレスポンスを変えることができます。以下ではIllegalArgumentExceptionのときに500、clojure.lang.ExceptionInfoのときはex-dataの:exception/typeの値によってステータスコードを変えています。Exception:"と流すようにしています。req))))))))こうなるようにwrap-exception-handlerを実装すると、以下のようになります。not-found-response)を作りました。実際に例外をふりわけるところはExceptionToResponseというプロトコルに任せて、それぞれの例外ごとに実装をできるようにしています。これによってwrap-exception-handlerでやっていることは非常に明快になりました。このようにRingミドルウェアを応用することで、例外ごとに任意のレスポンスを返すことができました。上記のwrap-exception-handlerを適用するDuctアプリケーションに適用するのは非常に簡単です。プロジェクトを用意するところから。次のコマンドを使ってDuctプロジェクトの雛形を作ります。+ataraxy今回はAtaraxyというデータでルーティングを記述できるライブラリを利用します。これはDuctで既にモジュール化されているため、簡単に使い始めることができます。次に先程のwrap-exception-handlerを使って、Ductから使えるコンポーネントを用意します。wrap-exception-handler)wrap-exception-handlerの実装については、既に説明したものをそのまま利用します。ミドルウェアのコンポーネント:demo.middleware/exception-handlerでは、単にwrap-exception-handlerを返すようにします。次に、このミドルウェアを適用するには、config.ednに以下のような記述をします。大事なところは:duct.module/ataraxyのキーに対応するマップです。module.ataraxyのREADMEに譲りますが、Ataraxyのシンタックスでいうresult部に対してメタ情報として任意のミドルウェアを指定することで先程のミドルウェアのコンポーネントを適用することができます。(@skikkh)です。Kubernetesページに反映されていたことです。閑話休題、弊社SPEEDAサービスでは大量のバッチジョブがHinemosを起点としてVM上で動作しています。SREチームではこのようなジョブ群を徐々にサーバから切り離して、コンテナライズを進めています。環境変数と環境が異なると掛け算式に増えていきます。これをkubernetesのCronJobでyamlハードコーディングすると容易に1000行を超えてしまい、管理上のコストも含め現実的ではありません。1そこで、kubernetesパッケージマネージャーを使用することにしました。その選択肢としてはHelmやKustomizeなどがあります。これらを利用することで環境毎に異なる設定値のリソースが作成できたり、複雑な依存関係を持つkubernetesリソース群をChartという一つのフォーマットにまとめることができます。今回、要件を満たすエントリが見当たらなかった為、利用事例として投稿させていだきます。単一のリストを利用してCronJobをループ処理する複数のリストを利用してCronJobをループ処理するスケジュールの時間毎に、異なる地域のバッチジョブを実行するサブチャートを作成して、一連のワークフローを一つのChartで再現する個別のyaml設定の注意点フラグで実行するジョブバッチを選択する完成したvalues.yamlおわりに仲間募集Kustomizeの場合まずはKustomizeで同様の利用を想定した際の構成を見てみましょう。下記ディレクトリ構成は公式のKustomizeのGithubの、サンプルディレクトリ構成から拝借しました。production環境といった環境差分をoverlaysで表現するのはKustomizeの方がいいかもしれませんが、Kustomizeの基本的なユースケースに照らし合わせてジョブを作成するとなると、次の例ようにCronJob毎にディレクトリを切る必要があり、管理コストが嵩んでしまいます。Kustomizeで多数CronJobを作成する例えば24個のAジョブと24個のBジョブ計48個作成する場合、overlays下に48個のディレクトリ構成ができてしまいます。以下がサンプルになります。table.yamlバッチジョブが20を超えてくるとなるとディレクトリで分割するのは現実的に厳しいと思います。同一テンプレートからスケジュール毎に生成する以上の理由から、KustomizeではなくHelmを利用することを決めました。Helmの場合Helmではアクションと呼ばれる制御構造によってリストをループ処理することができます。したがって、今回のケースではこちらを採用することにしました。Tillerのバージョンはv2.14.3を使用しています。複数の地域情報を取り出し処理ができる2バッチジョブを作成する必要がありました。これを実現するためには先述したループ処理を行う必要があります。実現方法としては「ループ処理をネストすれば可能」というのが答えなのですが、少しだけハマりどころがあったので、それも合わせてお話できればと思います。通常のCronJobをループ処理する場合、values.yamlに回したい変数のリストを作成し、rangeを入れればループ処理が可能です。単一のリストを利用してCronJobをループ処理するまずはスケジュール毎にCronJobを作成したい場合を想定してみましょう。以下の実行例ではスケジュール毎にスケジュールのインデックスをechoで出力するという設定をyamlで行います。testを利用しましょう。テストで検証するのであれば、busyboxイメージでechoを出力します。}}因みにyamlの可読性の為、最初に以下のような代入を行っています。}}values.yamlの設定は以下のようになります。]特に難しい部分はなく、rangeアクションで作成したいCronJobを囲むだけです。一つ注意しないといけない点として、CronJobの名前は一意になるようにしなければいけません。その為、全ての名前が一意になるように命名規則を考えてつけましょう。基本的にはループで回す変数名をつけるようにすれば大丈夫だと思います。3作成後、以下のhelmコマンドを実行します。.これでテーブルの数だけジョブを回すことができるChartのリリースができますね。複数のリストを利用してCronJobをループ処理する一つの変数の条件でループ処理ができたので、複数の変数のリストを使用してループする場合を考えてみましょう。スケジュールのループ処理内にテーブルのループ処理をネストするだけで作成できます。記述例としては以下のようになります。runしかし、例のようにスケジュール×テーブルという変数でジョブを回そうとすると失敗してしまいます。以下が失敗の際に出力されるエラーになります。{}失敗の原因は.のカレントスコープが「.Values.global.schedules」を向いているためで、.Values.global.regionが習得できません。回避策としては、ループの処理の際に、「常にグローバルスコープを持つ$を使用する」ことでこのエラーを回避できます。したがって、以下のdiffの変更点のように最初の記述でループしたい変数を別の変数に代入することでスコープを変えないままネストしたループ処理ができるようになります。CronJobのリソース名も一意にするため、テーブルの名前を更新しておきましょう。名前を一意にするためしかし、これでもまだ十分ではありません。スケジュールのindexがほしいのではなく、スケジュール(cron)毎に習得される地域の変数をCronJobのmetadataや環境変数に代入したいのです。libraryを利用してリストを取得するようにしています。このような形にしたのは、複数のバッチジョブを後述するsubchartに記述する際、values.yamlをDRYにするためです。全てのリストを1つづつ取得する関数がなかったので、次のような形で再現しています。}}values.yamlにはglobal.regionsを、scheduleのリスト長と同一のリストを加えましょう。china]これで、地域別のDBのテーブルの情報が取得できるようになりましたね。サブチャートを作成して、一連のワークフローを一つのChartで再現する実際には上記のようなバッチジョブが後続に存在しているので、これらをひとまとまりにして扱う必要があります。最後に、これらバッチジョブをひまとまりにして処理する方法を学びましょう。複数のjob(Dockerイメージが別)を扱うためにsubchartを採用しました。ServiceAccount関連のリソースやNetworkPolicyやNamespaceのようなグローバルなリソースは大本のChartにまとめ、各ジョブをsubchartに入れるという形を取ります。values.yamlの項目で、globalの変数と、そうでないsubchart毎のローカル変数を使いわけることで実現できます。以下にサンプルのディレクトリ構成を挙げます。各サブチャート毎に分化されたschedulesはグローバルの設定ではなく、個別のジョブ毎のローカルの設定になるため、各subchart内では、.Values.global.schedulesから.Values.schedulesのようにグローバルのスコープをローカルのスコープに変更しておきましょう。}}フラグで実行するジョブバッチを選択する後でsubhart毎にテストをするには、個別のsubchartだけを実行する必要があります。そのため、enabledを各subchartに記述します。end}}values.yamlに以下の設定を入れます。xxx...実行時に不必要なジョブに対してfalseのフラグを立てることで個別実行が実現できます。.上記は0101-jobだけがChartだけがデプロイされる例になります。テストに関して1つ注意点があります。テストを行う毎はテストの実行ジョブの順番が変わるのでご注意下さい。5完成したvalues.yaml最終的なvalues.yamlは次のようになります。Chart化しました。その他ハマりどころとしてはvalues.yamlのsubchart名と一致しないChart名、ディレクトリ名になっているとチャートがデプロイされないという事例がありました。名前を変更した際には確認するようにしましょう。Resourcesなど省略しているので、それぞれの環境に合わせて設定していただればと思います。掲げて業務に取り組んでいます。「挑戦しなければ、SREではないし、SREがなければ、SPEEDAもない」という意識で、日々ユーザベースのMissionである、「経済情報で、世界をかえる」の実現に向けて邁進しています。〜大規模イベントの運営ってどんなことやるの?〜Tweetこんにちは!SPEEDA開発チームの斎藤です。先月9月21(土)に開催された開発者向けイベント「XP祭り」は皆様ご存知でしょうか。今回は運営メンバーとして「XP祭り」に関わり、思いきりお祭りを堪能した私の視点から運営ってどんなことしてたの?(大変なの?)運営側だとどんな楽しいことがあるの?といったことについて少しだけ語らせていただき、イベントを創る側の魅力や楽しさが伝えられればと思います。XP祭りとは?毎年9月ごろに開催されるソフトウェア開発者向けの技術イベントです。講演者が培った知見、体験を元にした魅力的な講演、ワークショップが多数行われます。参加費用は無料!今年は18回目で、来場者数220人と大盛況でした。XP祭りの運営ってどんなことやるの?運営側がやることを大きく分けると、イベント当日までの準備と、当日の運営の2つに大別されます。XP祭りでは毎年、各出版社様から技術本を多数寄贈していただいております。これらは全て参加者および講演者の方に無料で配布させていただいております。etc...色々やることがあって大変に見えるかもしれませんね。XP祭りは今年で18回目なので、既にどんなことをどうやるかの大筋が決まっています。イベント会場は早稲田大学教授の鷲崎先生のご厚意で無償でお借りしています。運営をやるのが初めての私でも特に大変だと感じることはありませんでした。「運営がお祭りを楽しめるようにする」ということを意識されているそうで、長くイベントを続ける秘訣を教えていただいたなあと思いました。XP祭りの運営ってどんな楽しいことがあるの?これは色々ありますが、大きく分けると2つあると感じました。お祭りの準備や運営って、参加してくれる方が笑って満足してくれると嬉しいですよね。「XP祭り楽しかった」という感想を聞いたりすると「やって良かった」と思いますね。当日は参加者でもあるため、自分の気になる講演やワークショップに参加しちゃってOKです。たくさんの方々とつながりができました。同じようなことに挑戦している仲間や、偉大な先人の方と話ができるのはとても心強いです。困ったときに相談したり、良い知見が得られたときに共有したりと、コミュニティの強さって本当に素晴らしいなと思います。お祭りの後はやっぱり懇親会!終わりにほんの少しXP祭りの裏側を書かせていただきましたが、いかがでしたでしょうか。大規模イベントの運営でも実はそんなに大変じゃない運営として裏側からもお祭りを楽しめたという2点が伝わって、少しでも興味を持っていただけたのなら幸いです。(後はほんの少し勇気を出して飛び込むだけです。来年のXP祭り運営委員の会でお会いしましょう!)謝辞XP祭りの運営の皆様、ならびに講演、参加者の皆様、ありがとうございました。皆様のおかげで、XP祭りは今年も最高に楽しいイベントになったのではないか思います。〜大規模イベントの運営ってどんなことやるの?〜Tweetもっと読むコメントを書く2019-09-24【Clojure】Ductで始めるWebAPI開発ClojureTweetこんにちは!!SPEEDA開発チームの岡村です!!私たちの開発チームでは、先日チームメンバの野口が書いたこちらの記事に書かれているように、チームメンバーの入れ替えが頻繁に行われます。言う私も一ヶ月前に行われたチームシャッフルで、ClojureでDuctを使って開発を行うチームに移動しました。(Clojureほぼ未経験)私がClojure初心者だからこそ、これからClojureとDuctを始めて見ようかなと思っている方に対し、お伝えできることがあると思い、今回はDuctでWebAPIを作成する方法をご紹介しようと思います。DuctとはDuctはライフサイクル管理を行うライブラリ、Integrantをベースとしたサーバサイドのフレームワークであり、アプリケーション構造は、Integrantのコンフィグレーションマップによって定義されます。DuctとIntegrantの関係に関しては、弊社の中村がこちらの記事でも一度ご紹介しています。作成物CRUDの題材として定番な、TODO管理を下記リクエストで行えるAPIを作成していきます。指定したデータを削除するプロジェクト作成DuctプロジェクトはLeiningenを使って作成することができ、プロファイルを指定すると、それに合わせプロジェクト構成や設定ファイルを自動で生成してくれます。+postgresと指定しました。Todoを管理するデータベースも作成しておきましょう。今回はDockerコンテナで作成しました。*eREPLが起動したら、(dev)と入力し開発環境をロードします。(dev):loadedその後、(go)とコマンドを入力するとシステムを起動することができるのですが、DBへの接続情報をまだ記述していないため、下記の様なエラーが発生し、起動することができません。(ConnectionFactoryImpl.java:534).サーバはパスワード・ベースの認証を要求しましたが、パスワードが渡されませんでした。dev=>システムを起動させるため、DB接続情報を記述しましょう!/todo/dev/resources配下にある、dev.ednファイルを以下の様に変更します。このファイルはファイル名の通り、開発環境での設定を記述するファイルです。}Ductではednファイルにコンフィグレーションマップを書いていくことで、アプリケーションの構造を表現することができます。ここではduct.database/sqlというコンポーネントの初期化時に、データベースの接続情報が渡される用に定義しています。書き換えた後に、再度システムを起動させてみましょう。3000}:initiated上記の様に表示されていれば、システムが起動されています。curlでリクエストを送ってみましょう。http://localhost:3000{"error":"not-found"}errorが帰ってきますが、起動していることがわかります。利用して、システムの起動時にテーブルの作成と、テストデータの投入が行われるようにしましょう。先ほど編集したdev.ednを下記のように編集します。}システムを再起動させてみましょう。REPLで(reset)と入力すると、再起動することができます。:todo.migration/create-todos#2cd2c3f9:resumedこれでデータベースにテーブルが作成され、データが投入されました。一覧取得処理の実装まずはTodo一覧を取得する処理を実装していきましょう。/todo/resources/todo/に存在する、config.ednを下記のように編集します。[:todo.handler.todos/list]}という記述を追加しました。これは、/todosにGETリクエストが来た時、:todo.handler.todos/listコンポーネントで処理をするということを表しています。{}という記述も追加しました。これは:todo.handler.todos/listコンポーネントの初期化時に空のマップを渡すということを示しています。続いてハンドラーを作成していきます。/todo/src/todo/handlerに、todos.cljというファイルを作成し、以下を記述します。"OK!!!"}]))Integrantでマルチメソッドとして定義されている、ig/init-keyを実装することにより、コンポーネントを作成することができます。::listというのは、todo.handler.todos/listと同じ意味になります。これにより、先ほどconfig.ednで書いた設定と処理を紐づけることができます。戻り値は、Ataraxyを利用しているのでベクタで記述することができます。"OK!!!"というマップを返すようにしました。http://localhost:3000/todos{"message":"OK!!!"}レスポンスが帰ってくることを確認できました!それでは、実際にデータベースからTodoリストを取得し、返すように実装を変えていきます。/todo/resources/todo/config.ednを下記のように変更します。:duct.database/sql}に変更しました。#ig/ref関数を利用し、:todo.handler.todos/listコンポーネントは、:duct.database/sqlコンポーネントに依存しているということを示しています。:duct.database/sqlは、最初にdev.ednで記述したコンポーネントのことです。初期化済の:duct.database/sqlコンポーネントを受け取ります。次に先ほど作成した、todos.cljを以下のように変更します。後で作成する、データベース接続を行うBoundaryにDB接続情報を渡して結果を返すようにしました。第二引数にはコンフィグマップのコンポーネントに対応する以下のようなバリューが渡ってきます。:duct.database/sql}のことです。#ig/refと記述しているため、初期化された:duct.database/sqlコンポーネントが渡ってきています。続いて、実際にデータベースへの接続を行う層として、Boundaryを作成していきましょう!/todo/src/todo/boundaryにtodos.cljというファイルを作成し、以下を記述します。)DBへの接続情報を受け取り、clojure.java.jdbcを利用してデータベースにアクセスしています。次にデータベースへの登録処理を実装していきましょう。流れは一覧取得処理を実装した時とほとんど同じです。config.ednに/todosにPOSTでリクエストが送られてきた時の定義を記述します。{}}先ほどと違うところは、HTTPリクエストからパラメータを取得しているというところです。HTTPリクエストの情報はマップで渡ってきており、そこから登録に必要な:body-paramsの値を取り出しています。次にhandlerを下記のように変更します。id)])))無名関数の引数が一覧検索の時と異なっています。この無名関数の引数には下記のようなHTTPリクエスト情報のマップが渡ってきます。:post}そのため:ataraxy/resultを分配束縛させています。)jdbc/queryを使っても、もちろん実装できるのですが、jdbc/insert!を利用してみました。これまでと同様にして実装することができます!そのため説明は割愛させていただきますが、最終的に実装は下記のようになります。)まとめIntegrantの「アプリケーションの構造と実装を、明確に分けて開発を行っていける」という機能を利用して作成されたDuctは、ednファイルで各コンポーネント間の依存関係を明示でき、「何が何に依存しているのかednファイルを見ればわかる」といったとこや、提供されているモジュールを利用することにより、実装を手軽に行えるということに魅力を感じました。非同期Tweetこんにちは!SPEEDAプロダクト開発チームの成です。去年の秋ごろからRustを触り始め、徐々にRustの魅力に惚れられました。読みながら、Rustを少しずつ理解していくと、段々コンパイラーと仲良くなってきて、Rustを書くのも楽しくなりました。Server、色んな処理を並列化するBatchなどをRustで作ってきました。最近プロダクトのマイクロサービスの極一部もRustで作っており、幸せ感満喫です!!本日は、HTTPリクエストを並列化するときハマったことをお話したいと思います。Rustは独特なメモリ管理仕組みを持ち、安全かつRuntimeで発生したら世界が止まるFullGC的なものも一切ないし、高速な並列処理などが特徴です。カッコイイ言語と思いますので、本当に広がってほしいです。方々も是非書いてみてください!はい、宣伝は以上です。今日はサンプルコードを介してハマった点を説明させていただきます。使って並列処理を実現します。