CentOS7@Dockerで curl: (77) Problem with the SSL CA cert (path? access rights?)

3行で

  • CentOS7環境でhttpsなサイトにcurlすると curl: (77) Problem with the SSL CA cert (path? access rights?) で失敗する
  • OSのバグなので
  • touch /etc/sysconfig/64bit_strstr_via_64bit_strstr_sse2_unaligned すると通る

詳細

M1 Macでのdocker run時のみに該当の事象が起きて七転八倒していた。
証明書周辺の問題はわりによくある*1のでノイズも多く、原因を探し当てるのに大変苦労した🥺

ログはこんなで

$ curl -vvv https://github.com
* About to connect() to github.com port 443 (#0)
*   Trying 13.114.40.48...
* Connected to github.com (13.114.40.48) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* Closing connection 0
curl: (77) Problem with the SSL CA cert (path? access rights?)

CAfile, CApathの出力まで至らずにコネクションがクローズされているのが謎。
wgetは普通に通ることが確認できたので証明書には問題がないと判断し、インターネットの海に溺れていたところ以下を発見し解決に至った。

There was a curl bug in the distribution image of CentOS-7.

う、嘘だろ…

$ touch /etc/sysconfig/64bit_strstr_via_64bit_strstr_sse2_unaligned`
# 通るようになった!
$ curl https://github.com

なお今回の事象においては、同様のエラーメッセージで雑にググると出る

  • ca-certificates, opensslのreinstall
  • yum update, upgradeその他
  • update-ca-trust

なんかは関係ないので注意。んなわけないだろと思いつつも一応試したりして無駄足を踏んだ。

なおいまのところM1マシンでしか再現していないのも謎。でもとりあえず原因も特定できたし、もうゴールしてもいいよね?

*1:やれルート証明書がないだの、中間証明書がないだの、自己署名だと通らないだの

【読書メモ】モノリスからマイクロサービスへ

www.oreilly.co.jp

切り口

「必要十分な」ドメイン設計は有効

  • 正しい境界を設定することがマイクロサービス化の一歩
  • 「集約」の手法が有効
    • 実際のドメイン概念の表現
    • 一般的にライフサイクルを持つのでステートマシンとして実装できる
    • 外部からの不正な状態遷移要求に対してバリデーションができる
  • 集約の集合が「境界づけられたコンテキスト」
  • 集約もコンテキストも一種のサービス境界として機能する
  • あくまでも「切り出し」を目的としたDDDの適用であって、DDDをやることが目的でない点に注意
    • 分離の起点を判断するのに必要十分な情報を得られればよい
  • イベントストーミングの手法を取り入れるのもよい
  • 分離しやすさと、分離によって得られる利益で4象限を作ってもよい

マイクロサービスは手段の一つでしかない

  • ビックバンリプレイスの後には何も残らない
  • メリットとデメリットを見極めて小さく始める
    • FBが早く得られるほうが学びを得やすい・活かしやすい
  • マイクロサービスだけが正解ではない
    • モジュラーモノリスとか
    • そのままでは「分けないほうがいい機能」とか
      • 依存するサービス量が多い通知機能のようなものとか

進め方

コンウェイの法則

  • フロントエンドチーム、バックエンドチーム、DBAチームと組織が分かれているなら、アプリケーションもそのようになっている
    • これは新機能開発のときにすでにある層を横断して開発をしないといけないことを表す
  • 新しいプロダクトの形に合わせて組織も再編し、責任を再割当てするとよい

John Kotterの組織変革のための8段階のプロセス

by 企業変革力

既存システムのどこに痛みがあるのかを考える

  • 現在のペインポイントがどこで
  • どのような変化をもたらすことを望んでいるのか(ビジョン)
  • どのように目標に到達するのか(戦略)
  • をまとめる

本番投入しないとわからないことのほうが多い

  • どんなに小さい規模でもデプロイまでを1セットにする
    • たとえアクセスがこないとしても
  • ランチアウトした先で長く作業をしすぎないこと

あとは小見出しの通り

  • 一人でがんばってもうまくいかないのでビジョンと戦略をまとめて巻き込む必要がある
    • これは偉い人の口から言う
  • 小さく初めて短期的成果を得る・そこから学ぶ
  • 定期的なチェックポイントを設ける
    • 定量的・定性的
    • 定性面では「このPJ、うまくいってると思う?」とかでもいい
  • マイクロサービス化は「可逆的」
    • うまくいかなければ戻せばいい
    • 大きな投資を伴うような選択の場合は可逆性が失われるのでちゃんと判断しよう
  • 正解がわからない場合は「わからない」って言っていい
    • 解決したい問題と迷っているポイントが周りに伝わるということが利点
    • そのうえでその時点で正しいと考えている対処を始める
    • 時間(がもたらすスキルや経験)が解決の糸口になるかも

移行手順

後戻りの道を潰さない

  • リファクタを行うなら、リファクタ前後の実装を残して切り替えられるようにしておく
    • プロキシなどを用いる
  • 移行中のサービスがあるなら、完了するまではそこへの新しいフィーチャやバグ修正が入らないようにする
    • 移行とフィーチャの取り込みを並行してはならぬ
    • ロールバックしにくくなるので
  • とにもかくにも「インターフェイス

事例:Squareの「注文」

  • 客にとっての注文と
  • レストランにとっての注文と
  • 配送ドライバーにとっての注文
  • それぞれニーズが違うのに、ひとところにまとまってしまっており、デリバリー衝突が起きていた
  • 分離によってワークフローを分割しつつスケーラビリティと堅牢性を担保しようとした

まとめのまとめ

  • 十分な余裕をもって、合理的な意思決定をするために適切な情報を収集する
    • 誰かの真似をするのではなく、自分の問題とコンテキストについて考え、選択肢を評価し、前進しよう
    • 後から変更が必要になった場合には、変更を受け入れる姿勢を持ちながらそれを行うこと
  • マイクロサービスとそれに関連する技術やプラクティスの多くは段階的に導入することが重要
    • 他人の事例から学ぶべき教訓があるのは事実だが、自分のコンテキストでうまく機能するアプローチを見つけるには、時間をかけなければならない
    • その道のりを管理可能なステップに分けていくことで、アプローチをその都度適応でき、成功の可能性を最大限に高められる

DDD開眼した

新しいパラダイムを自身にインストールするときは、なんであれ少なからずブレイクスルーのような瞬間があると思うけど、今回はかなりのアハ体験を得たので拙いながらも書き記しておこうと思う。

まず読んだ本を雑にまとめたうえで、LL脳な自分が感じた壁とそれがどう取り除かれたかを書き散らかしていく。完全に自分向けのメモなので例とかコードとか置いてないけど、少しでも雰囲気が残せたら嬉しい。
なおご多分に漏れず肥大化したモノリスコードベースの分割したさがこれらのモチベーションの源泉で、モジュール化のアプローチと真逆に位置するRoRでなんとか責務を分解しようとした七転八倒*1の結果得た開眼なので、正攻法な理解ではないかも。

読んだ本

クリーンアーキテクチャ

Clean Architecture 達人に学ぶソフトウェアの構造と設計【委託】 - 達人出版会

前半はSOLID原則とデザインパターンのおさらい、後半はモジュール化とレイヤードアーキテクチャで責務を分割してっょぃアプリケーションを作ろうな!という本(雑)。
責務を分割するというのはどういうことなのか、インターフェイスとはなにか(その利点はなにか)、モジュール化による旨味はなにか、の答えがそれぞれ書いてある。

実践DDD

実践ドメイン駆動設計(ヴォーン・ヴァーノン 髙木 正弘)|翔泳社の本

いきなりエヴァンス本を読むと挫折するだろうとしてこちらを読み始めたものの、エヴァンス本で出たワードの解説は特にないので結局路頭に迷う。読了後なにもかもわからんが!?となったあなた、それは間違いではありません。
概念の説明と各論すぎる各論(Hibernateの使い方とか…)が入り混じっている・章どうしの循環参照が激しいせいで大変読みにくい。本書のリファクタリングを要求します。

とまあ、愚痴は置いといて、ひとまず1周流し読みする→インターネットで情報を補強しつつ試し書きする→もう1周読む、を繰り返すことで開眼に至った。

なお「ドメイン駆動設計 モデリング/実装ガイド」を間に挟むと開眼までのサイクルが早くなる。実践・実践DDD本といった内容。大変お世話になりました…。
ドメイン駆動設計 モデリング/実装ガイド - little-hands - BOOTH

モノリスからマイクロサービスへ

O'Reilly Japan - モノリスからマイクロサービスへ

モノリスに境界をもたせるのにDDDの集約やコンテキストを使うとよい、あくまでも分離のためにDDDのエッセンスを適用しよう、といったことが書いてあった。
境界を炙り出すのにイベントストーミングをやってみるというのは、今までは違う観点で機能やビジネスロジックを捉えることができてよいアプローチだった*2
一周してみて、一度アクセルを踏み切らないと(DDDをひととおり試してみないと)「エッセンスの適用」は難しいよと思っているところ。

壁たち

インターフェイスとモジュール

インターフェイスとは無縁の人生だった*3のでこの概念を取り入れるのに結構苦労した。「依存関係が逆転する」の意味と、main関数は究極の詳細であるということが腑に落ちたタイミングで分かった気になり、社のテックブログに寄稿した2エントリでの経験を経て乗り越えた。

Pure Kotlin+gRPC(protobuf)なWebアプリを作るまで - ロコガイド テックブログ
ServerSide Kotlin Appをマルチモジュール化する - ロコガイド テックブログ

当たり前すぎるけど、やはりインターフェイスとモジュールの概念のある言語で一通り書いてみるというのが大事。

DDDの戦略と戦術

実践DDD本の2-3章を読んでも戦略DDDとはなんぞやというのが分からないと思うけど、ざっくり理解をまとめると、「戦略」は設計思想なので、要件に対して責務を組み立て(ないしは分解)していく過程で使うといいという話だった。
LL脳は要件が与えられるとついついデータモデルから考え始めてしまうけど、これを押し留めて世界観を描くところからやると違ったアプローチが取れる。CQRSなんかが「違ったアプローチ」のいい例。
一方から入稿されたデータを他方で加工して閲覧させるようなユースケースの場合、このCQRS的なアプローチがとても有効なように思う。
「戦術」は立ち位置としてはクリーンアーキテクチャ(の実践)寄りというか、実際のコードをどういう粒度でモジュール化/カプセル化するかという話。前提(思想)がついてこないと片手落ちというのも頷ける。

クリーンアーキテクチャとDDDの折り合い

どちらも微妙に同じワードが出てくるからたちがわるい(エンティティとかサービスとか)。あとDDDでサービスが2種類出てくる(アプリケーションサービスとドメインサービス)のも厄介。「ドメイン駆動設計 モデリング/実装ガイド」にはこの混乱を避けるためにアプリケーション(サービス)層を「ユースケース層」として命名せよと書いてあった。頭いい…。
クリーンアーキテクチャでもDDDでもレイヤードアーキテクチャをベースに語られているけど、本当にDDDを実践するのならオニオン的アーキテクチャのほうがいいっぽい。
なおプロダクションコードでクリーンアーキテクチャをベースにDDDのエッセンスを少しずつ取り入れていってみたら、最終的に完全にDDDに飲み込まれた。中途半端な援用は混乱を招く。

エンティティと値オブジェクト

ここが最後の難関だった。端的に言うと「データストアから引いてきたデータをそのままエンティティにするのは間違い」ということなんだけど…。
正規化・非正規化のプロセスが挟まったとしても、データストアにあるデータをエンティティとしてマッピングする必要はなくて、エンティティと取るか値オブジェクト(プレーンなクラス)と取るかは「そのコンテキスト/ユースケースの中で状態を遷移させる必要があるか」で決めたらいいということ。そしてエンティティに紐付いたプロパティ(としての値オブジェクト)は、永続化に必要なデータ以外も持ちうるということ。
つまりユースケースの中で「エンティティを組み立てるのに必要な情報」と「エンティティを永続化するのに必要な情報」は必ずしも一致するわけではないと。これが腑に落ちるとドメインオブジェクトの表現力が格段に上がるなと実感した。
そしてここにたどり着くまでに随分時間がかかったことで「データモデル第一主義脳」の呪いが思いの外強いことにも気づくなどした。こわいね!

*1:この話ももう少しまとまったら記しておきたい

*2:なおこのアプローチはドメインエキスパートらとワイワイやることが推奨されているけど、いろいろあって1人でやりました 寂しい!

*3:golangがっつり書いたのもisuconくらいなもんで

assets:precompileでフロントエンドテストがコンパイルされたらtsconfigを疑え

環境

起きたこと

  • jest @testing-library/react あたりを使ってフロントエンドテストを書いた
    • もちろんdevDependenciesで
    • React Componentのテストの拡張子は xxx.test.tsx とした
  • テストファイルは app/javascripts 以下ではなく test ディレクトリを掘って配置した
  • production環境下の assets:precompiletest 以下のファイルもコンパイル対象になり、依存ライブラリを見つけられずにビルドがコケた

対応

webpacker.yml でも config/webpack 以下でもなく tsconfig.json 以下に以下を追加する

  "exclude": [
+    "test",
     "node_modules"
  ]

tsconfigのことすっかり忘れてwebpackerにexclude optionないじゃん〜と困ってしまった。せつない

React hooksのユースケースまとめ

プロダクションでのReact Appの立ち上げ・運用をやっとこ1サイクル回すことができたので、忘れないうちにいくつか知見を書き溜めておこうと思います。
しかし本当に変化が目まぐるしいですね。過去の薄まってしまった記憶を取り戻すためにチュートリアルを一回しして、さーてやっていき〜と思ったところで「クラス型はもうオワコン!これからはhooks!」と言われたときにはどうしようかと思いました(早めに気づけてよかったともいう)。

さて今回はそんなhooksについて。
ベーシックな解説は公式ドキュメントや各種記事に譲るとして、ユースケースに絞ったメモを残しておきます。

useState

ご存知stateですね。値のストアとsetterを提供してくれる、シンプルなhookです。
まあこれはそのまんまなんですが…、主にパラメータの受け渡し時に活躍してくれました。
コンポーネントに値を渡しつつ、onClick / onChangeハンドラでsetXXXして再描画させる、とか。そんな感じです。
モーダルの開閉にも役立ってくれますが、管理するステート量に比例して変数が増えていくのが(見通しの観点で)若干ネック。使い所が違う場合はreducerでまとめるわけにもいかず…。

useReducer

「よくわからん」「useStateとの違いがわからん」などと敬遠されがちなuseReducer。
本来使うべきでない用途で使うと可読性が著しく下がりますね。慣れるまでは「迷ったらstate」でいいと思います。
Formikなどに頼るまでもない、シンプルなフォームオブジェクトを扱う手段*1として使われることが多いかと思いますが、この子が特に輝くのは、前の値を参照してsetしたい場合かなーと。
後述のuseEffectの第2引数として渡す値を事前にクリーニングする、などの用途に役立ってくれました。

useEffect

非同期処理の担い手。正しくは、画面の描画後に1回発火する君。
第2引数に配列を渡した場合は、その中身が変化したタイミングでも再実行されます。
さらに、アンマウント時のクリーンアップ処理を書くこともできる。強力ですね。
バックエンドからデータをフェッチする処理なんかを書いていくと思うんですが、Autopagerのような「値が変わる処理が複数回走りうるユースケース」においてはこちらのような現象を引き起こしがちなので、useStateではなくuseReducerで払い出した変数を第2引数に噛ませておくと暴発せずに済みます。

その他、あるいはReduxについて

useContextとかuseRefとかは、何回か使いかけて結局やめました。
コンポーネントへの伝搬は、多少面倒でも {...props} でドカっと引き渡せちゃう(便利)(濫用注意)こともあって、少なくとも今の規模ではあんまり困っていません。
書き始めでは想定していなかった要件に対応するなどして、分岐や似たような振る舞いをするコンポーネントが増えた場合などに(リファクタの手として)有効な気がしています。こちらについてもまたいずれ、例とともにまとめます。
またReduxの導入ですが、今回は見送ってしまいました。チームにReactチョットワカル人材が(nヶ月前の自分を含め)あまりいない中で、Fluxアーキテクチャまで学習するコストが高くなりすぎることを懸念したためです。塩梅が難しいですね。

*1:objectを定義して引き回す

RDS for MySQL8ではSRSが空になるバージョンがある

  • 8.0.16, 8.0.17では INFORMATION_SCHEMA.ST_SPATIAL_REFERENCE_SYSTEMS が空の場合がある
  • 8.0.19では修正されているのでバージョンアップするといい

あらまし

Amazon RDS for MySQL(8.0) v8.0.17 にて geometry 型を使おうと思ったところ、うまくスキーマが適用できず
There's no spatial reference system with SRID 4326
SELECT * FROM INFORMATION_SCHEMA.ST_SPATIAL_REFERENCE_SYSTEMS したら0しか入ってない😫

3月に 8.0.19 がリリースされていたので、試しにバージョンアップしたら無事 SRS の table が作られていました。めでたし。

参考

amazon rds - RDS MySQL 8.0.16 has empty "INFORMATION_SCHEMA.ST_SPATIAL_REFERENCE_SYSTEMS" table - Database Administrators Stack Exchange

WEB+DB PRESS Vol.108にエッセイを寄稿しました

12/22発売の WEB+DB PRESS Vol.108 18周年記念特集「壁の先に見えたもの」にて、「“この先生きのこる”軸足を求めて」というエッセイをお寄せしています。

東京ではすでに先行発売されているとのこと!

f:id:ar_tama:20181220101630j:image

 

審議事案です。


さて、早速ご恵贈いただいた本誌を拝読しているのですが(メイン特集3つがまずとても面白い…!)、特集全体を通してステキな読み物シリーズとなっております。
自分の章を含めいち読者として楽しんで読むことができ、まずは胸を撫で下ろしています。

 

内容ですが、若手、ジュニア層向けの文章を期待されていそうな空気を勝手に察知したので、キャリア1~3年目の皆さまを想定読者に据えて書いてみています。
ちょうど転職の時期と重なったこともあり、自身にとってもキャリアや武器を見つめ直すよい機会となりました。
こういった文章は初めてで非常に難産でしたが…、少しでもどなたかのお役に立てたらとても嬉しいなと思います。ご感想などお待ちしています。

 

他の皆さまの章もすばらしく、laisoさんには勝手に強いシンパシーを感じ、豊田さんの視座の高さに身が引き締まり、藤原さんの項ではその貫禄に平伏しました(語彙が少ない)。

ぜひお手にとってお読みいただけると嬉しいです。なにとぞ!