Netflixでデビルマンを見た
深夜に調べ物をしていてそのお供に見た。ながら見だったんだけど、割とトラウマになった。。。どれくらいかというと、ぼーっとしてるとその辛いシーンが思い出されて陰鬱な気分になるレベル。 ただ本当に傑作だと思った。
以下激しくネタバレ含みます。
続きを読む2017年の振り返り
2017年は上半期で振り返ってた suzan2go.hatenablog.com
2017年の下半期振り返り
11月に転してた。
7月
7月の最初には関わっていた決済回りの機能追加プロジェクトが無事リリース。かなりリファクタリングもしたし、決して単純な機能ではなかったが大きなバグも起こさずにいけたのは安心したし自信になった。
7月の後半からマネージャーから打診を受けてリーダー的な役割をやることになった。この時点で退職を考えていたというか既に内定が出ていたのでリーダー的な役割を引き受けるか迷ったけど、正直に話したところそれでもやってみてほしいということだったので頑張ることに。
8月
リーダー的な立場になり数値を追っていくことや、ビズデブ的な人たちとの関わりなどこれまで以上にやることになったが、1つ視座が上がった感じで割と楽しめた。
KARTEというツールを導入して、キャンペーンとかサイト内プロモーションをエンジニア無しに大体できるようになったのが自分のやった仕事としては大きいと思う。導入までは結構頑張ってその後の運用は優秀な新卒氏に任せたんだけど、ガンガン使い込んでいてとても頼もしかった。半分冗談でKARTE大臣!と呼んで任せていたら本当にめちゃくちゃ詳しくなっていって、名をつけて任せるって大事だなーと実感した。 karte.io
今も活用されているようで嬉しい。 qiita.com
9月
転職後に触ることになりそうなKotlin + Spring Bootの勉強をプライベートで始めていた。
9月後半からは社内でScalaも始まってたので、Kotlinで勉強していたことやSpringでのレイヤーわけは地味に役に立った。
10月
サービスの運用負荷を下げるためのサポートの人向け機能開発とか、自分が過去に開発に関わったサービスのリアーキテクチャとか、自分が rails new
したサービスの面倒を見ていた。サービスのリアーキテクチャは、完全に自分が(期間的に)やりきれない案件だったので、自分の理想を押し付ける形にならないように、実際に手を動かす人と認識を合わせることを意識した。その後どうなったかは聞けていないんだけど、頑張って欲しい…すみません…
このタイミングで祖母が亡くなったりしてめちゃくちゃドタバタしたものの、サポートの人にお願いされていた管理系の機能は全てリリースできたのでよかった。
そして10月の後半は2年半在籍したスタートアップ?の最終出社日だった。2度目の転職。何で転職したかというと主に理由は二つ。
- 条件面
- 技術的に今と違うことがやりたくなった
会社の公式エンジニアブログに何故か退職エントリーを書きました…
11月
今思うとツールだけの問題ではないんだけど、前職で当たり前に使っていたツールが使えないので転職してすぐは結構テンションが下がっていた。
単純に慣れなんだとは思うけど、当たり前に使っていたツールやサービスが使えなくなると思ったよりテンション下がるんだな
— すーさん二号 (@suusan2go) 2017年11月3日
あと入社してしばらくお腹こわしていたんだけど、今思うとこれ明らかにストレスだな…
無限に胃でガスが生成されてる感じで凄く辛い
— すーさん二号 (@suusan2go) 2017年11月9日
破裂しそう
この辺のお気持ちは以下で表明している。 suzan2go.hatenablog.com
仕事内容的な話でいうとgRPC + Spring Boot + Rails(これはこれから) + Nuxt.js なプロジェクトをほぼほぼ1人で回している。当初はgRPCやるつもりなかったんだけど、ちょっと触ってみると思ったよりも良いものだった。
DDDを実践するためにこういう本を買って読んでいるんだけど、自分がやっているのはレイヤードアーキテクチャ(or オニオンアーキテクチャ or クリーンアーキテクチャ)なだけで所謂 軽量DDD の域を出ていないなぁと思う。大分ドメインの知識がついてきたので、今年はドメインエキスパートと話して諸々すり合わせをしていきたい。
- 作者: ヴァーン・ヴァーノン
- 出版社/メーカー: 翔泳社
- 発売日: 2015/03/19
- メディア: Kindle版
- この商品を含むブログ (2件) を見る
12月
Slackが使いたすぎて、Slackを入れたいという話をして資料を作って、偉い人に持っていったら何やかんやあって導入が決まった。過去の経緯とか聞いてると、色んな人の下準備が色々あったので、自分の提案で通ったって感じっぽい。
他のチャットツールをディスるわけではないけど、現時点でやっぱり開発用のチャットとしてはSlackが最強だなーと。GitHub(会社ではGitLabだけど…)の通知を垂れ流すだけでも情報共有という意味ではかなり価値があるし、セキュリティや言語、FW関連の情報をRSSで流せるのもいい。
あと振り返り・プランニングの習慣を他チームに広めたりしていた。振り返りでとりあえずKPTやってみたんだけど、めちゃくちゃいろんな意見が出て他チームながらとても有意義だった。Problemとしてとても重い課題(組織構造的な話)がでたんだけど、それでも「XXと話す場を作って相談してみる」という具体的なTryが出て実行されたのはとても良かった。
まとめ
11月の転職が大きな出来事でした。前職は不満が1つもないといったら嘘になるけど、エンジニアとして働く環境という意味ではとても良い会社だったなーと改めて気付かされました。そして、自分が当たり前に享受していた諸々は決して当たり前ではなかったなーというのを実感して、感謝の気持ちでいっぱいです。
現職はポジティブに捉えると改善しがいがあることが沢山あるし、色んなことを任せてもらっているので、メインのプロジェクトと平行して頑張っていきたい。とはいえ段々と手が足りなくなってきた感はあるので手伝いたい人ご連絡ください。
改善しがいがあることが多い(しかも自分の経験が役に立ちそう)というのはとても嬉しいことなんだけど、一方でそれをやるために転職したわけではない…という思いは正直ある。知り合いから「組織を変えるには、それなりの立場、権限、報酬がセットじゃないと消耗するだけで得るものがない」とも言われているので、かかる労力や期間がどれくらいかというのはぶっちゃけ結構シビアに考えている。
2017年下半期の抱負の進捗
機械学習
進捗ダメです
アプリ
Spring Boot + Kotlin + gRPCの勉強に消えていきました・・・
2018年の抱負
力尽きたのでまた週末に…
自分が仕事で使うツールやサービスは割とモチベーションに影響するのだなーという話
※あくまで自分にはそうだったという話
所謂スタートアップと言われる会社から、それなりの規模の会社に転職してもうすぐ2ヶ月くらいになる。
今の会社に転職してくるときに、開発に使っているツールについては説明を受けていたし、当然それを知った上で入社したのだけれど、実際に使ってみると思ったよりもテンションが下がった自分がいた。
特に以下のようなソフトウェアエンジニアとして日常的に使うツールのグレードが下がると(正確には必ずしもグレードが下がったとはいえないものもあるんだけど)、辛かった。
- チャット
- ソースコード管理
- ドキュメント管理
こういう周辺のツールにモチベーションが左右されてしまうのはどうなんだろうと思っていたし、転職で会社を選ぶ時にも割と軽視していたのだけれど、自分には重要な要素だったようだ。
正直な話、入社して最初の週末は人事の方や誘ってくれた人に頭下げて辞めさせてもらおうか…という考えが頭をよぎる程度にはテンション下がっていた(今思うと単純にツール・サービスだけの話しではなく、環境が変わったとか複合的な要素が絡んで必要以上にナーバスになっていたのだけれど)。
ただ「今いる環境を良くしていくことが出来なければ同じことをどこに行っても繰り返すことになるのでは?」と思い直し、「もっとこうしたい」ということを発信してみると、賛同してくれる人がそれなりにいることがわかった。
そういった声をいわゆる偉い人達も後押ししてくれていたり、他にもXXを改善したい!と手を上げる人が出てきたりして、今は色々と良い方向に改善していきつつあると感じる。
またおこがましい言い方なんだけど、自分がそういう流れを作れた気がしていてそれがちょっと嬉しい。
全くまとまりのない文章だけど、Slack導入が承認されたのでその記念に。
Slack導入のトロフィー解除したぞ!
— すーさん二号 (@suusan2go) 2017年12月19日
grpc-gatewayでMetadataに詰めたエラーの内容をJSONに詰めてRESTクライアントに返したい
引き続きgRPCの話。
gRPCでエラーをクライアントに返したい場合、通常だとステータスコードとエラーメッセージしか返せない。例えばアプリケーションレベルのバリデーションエラーみたいなものを返したい時、メルカリさんの資料によるとMetadataに詰めて送ると良いらしい、
gRPCがクライアントのときは詰めたMetadataを読み出せばいいんだけど、grpc-gatewayでRESTのクライアントに返す時にはどうしたらよいか調べた。
grpc-gatewayのエラーハンドリングをカスタマイズする
実はGitHubのwikiに How to customize your gateway
というのがあって、そこに結構色々と書かれている。
How to customize your gateway · grpc-ecosystem/grpc-gateway Wiki · GitHub
で、Wikiから辿った先にあるブログに実際に結構丁寧にエラーレスポンスのカスタマイズ方法が乗ってるので、それを参考にすればよい。
fun run() error { runtime.HTTPError = CustomHTTPError // 省略 } type errorBody struct { Error string `json:”error"` ErrorDetails []ErrorDetail `json:”errorDetails”` } type errorDetails struct { Field string `json:”field”` Message string `json:”message”` } // おもにgRPCのMetadataをerrorBodyのような構造に変換し、クライアントに返すためのカスタムハンドラー func CustomHTTPError(ctx context.Context, _ *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, _ *http.Request, err error) { const fallback = `{"error": "failed to marshal error message"}` w.Header().Set("Content-type", marshaler.ContentType()) w.WriteHeader(runtime.HTTPStatusFromCode(grpc.Code(err))) eb := errorBody{ Err: grpc.ErrorDesc(err), } md, _ := runtime.ServerMetadataFromContext(ctx) for k, v := range md.TrailerMD { eb.ErrorDetails = append(eb.ErrorDetails, errorDetail{ Field: strings.TrimSuffix(k, "-bin"), // バイナリで帰ってくる文字列は-binのprefixがつくので、クライアントが扱いやすいよう消す Message: v[0], // サーバー側では文字列としてしか入れていないが、何故かArrayで入ってくるの最初のものだけ取得する }) } jErr := json.NewEncoder(w).Encode(eb) if jErr != nil { w.Write([]byte(fallback)) } }
Go書くの久しぶりすぎてこんな感じでよかったか全然自信ないけど、一応やりたいことは実現できた。
gRPCをブラウザで使いたい
引き続きgRPCについて調べている。
2017年11月現在では現状gRPCはそのままブラウザ上で動かすことが出来ない(Node実装はあるけどブラウザでは動かせない)。
現状ブラウザでgRPCを動かしたいと思ったら二つの道があるようだ。
grpc-webを使う
これはgRPCサーバーの前段にプロキシサーバーを立てることにより、ブラウザ環境でgRPCのクライアントを動かせるようにするというもの。
import {grpc, BrowserHeaders, Code} from "grpc-web-client"; // Import code-generated data structures. import {BookService} from "../_proto/examplecom/library/book_service_pb_service"; import {QueryBooksRequest, Book, GetBookRequest} from "../_proto/examplecom/library/book_service_pb"; const queryBooksRequest = new QueryBooksRequest(); queryBooksRequest.setAuthorPrefix("Geor"); grpc.invoke(BookService.QueryBooks, { request: queryBooksRequest, host: "https://example.com", onMessage: (message: Book) => { console.log("got book: ", message.toObject()); }, onEnd: (code: Code, msg: string | undefined, trailers: BrowserHeaders) => { if (code == Code.OK) { console.log("all ok") } else { console.log("hit an error", code, msg, trailers); } } });
実際に試してみると、確かにブラウザからgRPCが使えた。GitHubを見るとGo前提っぽく感じるけど、grpcwebproxyが単体で提供されているので、例えばバックエンドはGoでなくてもgRPCサーバーの前段でこのプロキシサーバーを起動させてあげれば良い。
grpc-web/go/grpcwebproxy at master · improbable-eng/grpc-web · GitHub
そうなんだけど実際に試してみると、クライアント側でセットしたメタデータがサーバーまでたどり着かない。
調べてみたら同様の症状の人がIssueを上げているよう。ここで一旦grpc-webは諦めて、次のgprc-gatewayの方を触ってみた。
grpc-gatewayを使う
こちらはgRPCのバックエンドサーバーの前段において、RESTのエンドポイントを提供するというもの。grpc-webとは違い、protoファイルにも手を加える必要がある。
syntax = "proto3"; package example; + +import "google/api/annotations.proto"; + message StringMessage { string value = 1; } service YourService { - rpc Echo(StringMessage) returns (StringMessage) {} + rpc Echo(StringMessage) returns (StringMessage) { + option (google.api.http) = { + post: "/v1/example/echo" + body: "*" + }; + } }
grpc-gateway は、RESTのエンドポイントを作るための実装だけではなく、swagger定義も出力出来るようになっている。なので、gRPCが使える環境の場合には普通にprotoファイルから生成したクライアントを使い、RESTを使う必要がある場合にはgatewayの出力したswagger定義からRESTクライアントを生成すればよい。
protoc -I/usr/local/include -I. \ -I$GOPATH/src \ -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ --swagger_out=logtostderr=true:. \ path/to/your_service.proto
まとめ
grpc-web
の方がprotoファイルに余計なものを書かなくてすむので後々はこっちの方向性かなーと思った。でも、現状だとまだ grpc-gateway
を使った方が良いのかなーという感触。
Rails + SpringBootでgRPCする方法について色々調べた
RailsのバックエンドとしてSpring Bootを置いてgRPCでやりとりするみたいなのをどう実現するかを調べている
RubyからgRPCを使う
クライアント側はこれが参考になった。proto
からGemの中身を生成して配布するの良さそう。
クライアント側でgRPCを扱うコードはこんな感じになる
stub = Snip::UrlSnipService::Stub.new('0.0.0.0:50052', :this_channel_is_insecure) req = Snip::SnipRequest.new(url: 'http://shiladitya-bits.github.io') resp_obj = stub.snip_it(req)
Spring BootでgRPCを使う
これを使うのが楽そう。 @GRpcService
のアノテーションを付与するだけで、 Spring
と gRPC
を共存させることができる。
@GRpcService public static class GreeterService extends GreeterGrpc.GreeterImplBase{ @Override public void sayHello(GreeterOuterClass.HelloRequest request, StreamObserver<GreeterOuterClass.HelloReply> responseObserver) { final GreeterOuterClass.HelloReply.Builder replyBuilder = GreeterOuterClass.HelloReply.newBuilder().setMessage("Hello " + request.getName()); responseObserver.onNext(replyBuilder.build()); responseObserver.onCompleted(); } }
実際にアプリケーションを作るにあたって
クライアントをどこで作るか
.proto
からクライアントをどこで作って配布するかみたいなのを考えていた。 .proto
を vendoringするためのツールを作っている方もいるみたい。
現在のところはgradleのビルドの中でRubyクライアントを作っている。クライアントが決まっていて1言語だけなら、これがコスパよいかなという気がする。
このgradleのプラグインで、Rubyクライアントも生成できそうなんだけど、なぜかCLIで grpc_tools_ruby_protoc -Iproto --ruby_out=lib --grpc_out=lib proto/*.proto
としたときにできる *_services_pb.rb
が生成されない。
このIssueと関連ありそうな気がするけど、コードまでは追えてない。
しょうが無いので、無理やりgradleの中でコマンドを実行してRubyのクライアントを生成するようにしている。 キレイにやるならCIで生成するとかかなぁ。
エラーハンドリング
まだ良くわかってないが、この辺を読んで見るつもり。というか、この公式のexamplesもっと早く見ておけばよかった・・・
色々資料を読んでいると、エラーの詳細を返したいときはメタデータに入れるのが一般的なのかなー。例えばバリデーション的なものをやりたいときに、gRPCからどんな風にエラーを返せばいいんだろ。
grpc/examples/ruby/errors_and_cancellation at master · grpc/grpc · GitHub
今のところの感想
なんとなく行けそうなイメージは出てきたけど、まだまだ色々調べなきゃいけないことが多い。
gRPCだけでなく、SpringBootやgradleとかもまだまだ「全然わからない。俺は雰囲気で(ry」って感じなので、ちゃんと作っていくとまだまだ色々ありそうな予感。
GoでGitHubのrepositoryをキレイにするツール作ってた
作ったのは大分前なんだけど、そういえばブログに書いてなかった。
こういうのの名前考えるのめっちゃ苦手で、好きなMGSのキャラクターから名前とったものの、結構有名っぽいOSSに同名のものがあってしくじった感ある。いい名前があればIssueください…
何をするツール?
GitHubのrepositoryのお掃除をするツール。と言っても、現在のところはReleaseを消す機能しかない。
# clean suusan2go/hoge repo releases created 1 months ago $ raiden releases clean -r hoge -o suusan2go --months 1
GitHubのRelasesは何か特殊な構造になっていて、GitのタグとGitHubで作成されたReleaseというのが混在する形になっている。なのでGitHubのAPIからReleasesを消してもタグは残っちゃうし、タグだけ消してもReleaseは残るという結構面倒な感じになっているが、このツールなら上記のコマンドで一気に消せる。
ちなみにタグだけを消す方法もあります。
# clean suusan2go/hoge repo releases created 1 months ago $ raiden tags clean -r hoge -o suusan2go --months 1
なんでこんなの作ったの?
会社(前職)のデプロイフローのなかでタグを作ったりReleaseを作ったりしていたんだけど、デプロイの度に作っちゃうもんだから積もり積もって数千件に達していてGitHubからpullしてくるのがちょっと遅くなっていた(らしい。インフラ見てる同僚談) GitHubの画面からポチポチは無理な感じだったので、シュッっと(実際はちょっとかかったけど)Goで作ってみた。
Goに詳しい人から教えてもらって、Cobraという奴を使ってみたんだけど、結構簡単にそれっぽいCLIツールができてしまって感動。
今後の展望
放置されたIssueやPRを閉じる機能とかそのうち作ろうかな‐と思っていたものの、今の職場はGitLabなんでどうしたもんかな。 GitLab悪くないんだけど、やっぱりGitHubが恋しいよ。