アカツキインターンに行ってきて考えたこと

株式会社アカツキさんにてありがたいことにインターンをさせていただきました。 きっかけ したこと Go1.11.4対応/調査 多段カナリアリリース カナリアリリース中に特定のAPIが叩かれたかどうかレポートするシステム(Ensurerun) 技術的に学んだこと 痛感した自分の弱み 遅い 進捗報告 質問が下手 そのほかいろいろ思ったこと/得たこと インターン生という感覚が薄かった 固くない 「どれだけちゃんとやるのか」の感覚を学んでいきたい 結局何を学んだの? まとめ きっかけ 直接的なきっかけとしては Supporterz の 1on1 で人事の方とお話させていただいたことです。 ただそれまでにも、大学のZliサークルで開催した企業さんとの合同LT会や、前の年の1on1イベントなどで何度かお話させていただいたこともあり採用に力を入れている企業さんだなという認識はありました。ただゲーム系の企業は今のところどこもRails/Unityの人材を探している印象が強く、あまり興味を持って話を聞いたことがありませんでした。 しかし去年の夏にnatumnくんがアカツキのATLASチームというところでインターンをした話を聞き、「なんだかGoでゲーム基盤を開発しているらしい」「とても働きやすい環境らしい」という印象を持ちました。 そこで1on1で人事の花田さんとお話した際にインターンをお願いし、2月の12日から3月1日まで受け入れていただくことになりました。 したこと 配属していただいたのはnatumnくんと同じATLASチームです。 主に課金基盤アプリケーションのカナリアリリース周りを触っていました。 Go1.11.4対応/調査 やっていた期間: 2 / 12 - 2 / 13 これはもともとIssueとしてあったタスクではなく、環境構築中に手元でアプリケーションのビルドができなかったことからIssueを作ったものです。 エラー内容からどうやらいくつかのダウンロードしたGoのモジュールがgo.sumに記述されたチェックサムに適合していない、というもののようでした。 go: verifying github.com/aktsk/nolmandy@v0.1.2: checksum mismatch go.sumを削除すれば正常にビルドできることから、該当のモジュールにForce Pushやタグの付け替えがありチェックサムが変更された可能性をまず考えましたが、そのような心当たりはないという話を聞き、頭をひねっていたところ cmd/go: symbolic links not dropped from repo [1.11 backport] · Issue #29191 · golang/go

雑にワンライナーのシェルスクリプトをHTTPサーバーとしてデプロイする

[追記] 執筆後にGAE-FEがGCEと同様の値段がかかる&&最小インスタンス数が1以上であることから無茶苦茶お金がかかることに気づいたため、この記事はなかったことになりました。 以下本文 自分はシェルスクリプトが好きなので、いろいろなことをシェルスクリプトでやるのですが、たまにシェルスクリプトがHTTPサーバーであってほしいときがあります。 話は変わって最近AtCoderをやろうかなと思っているのですが、AtCoderにはABC、AGC、ARCの3種類の定期開催のコンテストがあります(参考: AtCoder Grand Contest (AGC) について:suda_k0のブロマガ - ブロマガ)。しばらくABCに参加しようかなと考え、公式のGoogle Calendarを見ると、 ABC以外も混ざっている!! ABC(AtCoder Beginner Contest)の予定は表示しておきたいけど、他のAGC(AtCoder Grand Contest)などの参加する予定のないものは表示しておきたくないのでどうにかフィルタしたいところです。 ところでGoogleカレンダーのカレンダーはiCal形式でインポート/エクスポートできます。自分はiCal形式を前に少し触ったことがあったので、シェルスクリプトでフィルタをしてみようと思いやってみたのが以下です。 curl https://calendar.google.com/calendar/ical/atcoder.jp_gqd1dqpjbld3mhfm4q07e4rops%40group.calendar.google.com/public/basic.ics \ | sed -e '/BEGIN:VEVENT/{:l N; /END:VEVENT/!bl; /\(Beginner\|ABC\)/!d;}' 1行目のcurlで取ってきているURLが先の画像でお見せしたAtCoder公式のカレンダーのiCalです。これをsedでいい感じに"Beginner"や"ABC"を含むものだけにフィルタします。雑いですが個人用なのでこれで十分です。 これで現時点でのABCのみのカレンダーを作ることができましたが、今後も自動的にアップデートしてほしいものです。このシェルスクリプトにURLを与えて、URLが叩かれるたびに新しいカレンダーが出力されるようになれば完璧なのに… ここまでが前置きです。 やりたいこと HTTPサーバーを立っている リクエストが来るとシェルスクリプトが実行され、標準出力がレスポンスで返される これをできるだけ楽に作りたい。 検討したサービス 一番に思いつく方法はEC2やGCEなどのインスタンスをまるごと借りるタイプのものですが、お金のない学生なので選択肢に挙がりません。 次にAWS Lambdaでシェルスクリプトが動く、みたいな話があったのを思い出しましたが、個人のプロジェクトはGCPで統一しているので管理コストなども考え今回は除外させていただきました… すみません(AWSに慣れている方は一番の選択肢になるかもしれないです)。 同様にGoogle Cloud FunctionsやFirebase Functionsでシェルスクリプトが動いてほしいという希望を持ちましたが、残念ながら対応していないようでした。 そして今回採用したのがGoogle App Engine(GAE) Flexible Environment(FE)です。FEは使ったことがなかったのでどれだけ楽にできるのか不安なところがありましたが、慣れればまあそこそこ頭を使わずにできそうな感じだったので紹介します。 GAE-FEでシェルスクリプトを実行するHTTPサーバーを立てる シェルスクリプトの公式のランタイムはありませんので、カスタムランタイムとしてDockerイメージをデプロイすることにします。というわけでまずHTTPサーバーとシェルスクリプトを含むDockerfileを書きます。 FROMalpineRUN apk add sed bash curl coreutils busybox-extrasCOPY index.cgi /www/cgi-bin/index.cgiRUN chmod 700 /www/cgi-bin/index.cgiCMD httpd -h/www -p$PORT -fサーバーにはBusybox httpdを使用しました。BusyboxがもともとAlpineに入っていた(といいつつ busybox-extras を別途入れる必要があります)のと、そこそこ楽そうだったからです。あとsedやcoreutilsを入れているのはGNUのコマンドが使いたかったからです。シェルスクリプトに必要なコマンド類はこれらに加えてfindとか入れておけばだいたいのスクリプトで足りるイメージがあります。

VSCodeの見た目をシンプルにする

自分はほとんど使わなかったり要らないUIが目障りなのが嫌いなので、少しだけカラースキーマを書いてこんな感じにしてみました。 "workbench.colorCustomizations": { "widget.shadow": "#0c0c0c", "statusBar.background": "#111", "statusBar.foreground": "#555", "statusBar.debuggingBackground": "#111", "statusBar.noFolderBackground": "#111", "panel.background": "#111", "sideBar.background": "#111", "activityBar.background": "#111", "activityBar.foreground": "#555", "activityBarBadge.background": "#555", "activityBarBadge.foreground": "#111", "editor.background": "#111", "editorOverviewRuler.border": "#555", "editorGroupHeader.noTabsBackground": "#111", "editorGroupHeader.tabsBackground": "#111", "editorGroup.border": "#111", "editorLineNumber.foreground": "#555", "editorLineNumber.activeForeground": "#555", "tab.border": "#111", "tab.activeBackground": "#111", "tab.activeForeground": "#aaa", "tab.activeModifiedBorder": "#444", "tab.activeBorderTop": "#333", "tab.inactiveBackground": "#111", "tab.inactiveForeground": "#444", "tab.inactiveModifiedBorder": "#333", "scrollbar.shadow": "#0c0c0c", "scrollbarSlider.background": "#333" }, "editor.overviewRulerBorder": false ただそもそも要らないものは表示しなければ目障りにならないので、Activity Bar(左のやつ)とMinimapは結局非表示にしてしまいました。 一瞬Theme拡張として公開しようかと思いましたが、Themeにはシンタックスハイライトの設定も含めなければならないということでやめました。自分のsettings.jsonに書いておけば好きなほかのTheme拡張と組み合わせられるので。

[Linux] VSCodeでGlobal Menuを有効にする

KDEやGnomeにはGlobal Menuという概念があり、アプリケーションのAltキーでフォーカスされるようなよくあるメニューバーをアプリケーションウィンドウの中ではなくその他の好きなところに(設定次第で)置くことができます。Macのメニューバーに似てますね。 ↑アプリケーションの中にある通常のメニューバー。自分は普段はこうではなく、Global Menuを使用して画面の左上にマウスHoverしたときのみ表示されるようにしています。 しかしVSCodeのメニューバーをこのように表示することができていませんでした。クロスプラットフォームのアプリケーションでは対応していないことが多い1ので、諦めてAltキーでトグルする設定にしていたのですが、 たまたまこちらのStack Overflowを見てVSCodeをGlobal Menuに対応させることができてしまいました。 [Linux] KDE’s menubar button does not work · Issue #34510 · Microsoft/vscode 自分はArch系のディストリなので、以下でうまく行きました。 $ yay libdbusmenu-glib libdbusmenu-glib というものが何なのか気になりますが、とりあえず今日はここまで。 おそらくQtやGTKを適切に使用してメニューバーを実装しないとGlobal Menuとして扱えないのでは無いかと思っています。 ↩︎

TRPGキャラクターシートの管理のこれから

この記事はTRPG なんでも Advent Calendar 2018の24日目の記事です。 こんにちは。まだまだTRPG初心者(クトゥルフPL2回、アマデウスPL1回)の@acomaguと申します。プログラミングをたまにします。 今回はキャラクターシート置き場についての話をします。自分はクトゥルフTRPGのキャラクターシートをキャラクター保管所さんで管理しているのですが、キャラクターシートを保存できるサイトは他にもいくつかあります。 TRPGキャラクターシートアーカイブスさん とらぷぐ.comさん オンセンSNSさん …などなど。(クトゥルフ以外だとまたいろいろあるみたいですね) まあ言うほど無いんですが、それでも選択肢があります。ただ、ほとんどの方は自分と同じくキャラクター保管所さんを使っているような気がしています(あくまで自分の観測範囲ですが)。理由を考えると、いろんなサイトで推奨されているとか、数多くのTRPGに対応している、技能値の割り振りがしやすいなどがあると思います。 自分もそこそこ満足していたのですが、何度かアクセスするうちに不満点も見えてきました。「連携できるツールが少ない」ことです。 チャパレさんなど一部のツールはキャラクター保管所さんからの読み込みに対応していますし、キャラクター保管所さんのほうではどどんとふ連携に対応しているのですが、他のほとんどのオンセツールなどでは自分で能力値と技能値を手入力する必要があります。また、クトゥルフWebダイスさんのようなキャラクター作成ツールからの読み込みにも対応していません。このあたりの連携ができるサービスが見つからないのは、キャラクター保管所さんがキャラシートに書き込むためのAPIを提供していないことが原因と考えられます。 「ダイスを振る → キャラクターシートに保存する → オンセツールに表示する」までを一度も手入力することなくやりたかったのです。 このあたりのしんどさを解決しようと以下のようなツールを作ってみたりもしました。 acomagu/cstoml: TRPGキャラクター保管所 -> TOML キャラシートをパースしやすく人間も読み取りやすいTOMLに変換し、GitHubで管理しようという発想でした。しかし例えば能力値が変更された際にオンセツールが自動でGitHubにコミットを投げるというのも考えづらく、連携のしやすさという点ではこちらも貧弱なものでした。 また、単にキャラクターシートのデータを取得/更新できるだけではなく、リアルタイム性も担保したいと考えていました。というのも今後GMをやる上で、PL全員の能力値の現在値をまとめて閲覧できるビュワーがほしいと考えていたからです。単なる保存場所としてのWebサイトとは一線を画したものが必要でした。 そこまで考えて、私は Solid が解決策になるのではと気づきました。 Solidとは ちょっと一言で表すのが難しいのですが、もし無理やりその一言を選ぶのならばやはり「データをユーザの手に取り戻す」でしょうか。 仕組みを大まかに説明すると、ユーザーはサービス提供企業それぞれに個人情報を提供するのではなく「Solid POD」と呼ばれる保管場所(クラウドあるいは自分のサーバ)上に情報を保存し、Solid上のサービスを使う際、どの情報をサービス側に提供するかを選択する。これにより、ユーザーが自分の情報を管理しやすくなるだけでなく、サービスを利用した際に生じる個人データもアプリと分離されてPODに保存されるので、サービス側も大量のデータを収集する必要がないという(Solid Explainedページより)。 気になったエンジニアの方はぜひ公式サイトのMake a Solid app on your lunch breakをやってみてほしいのですが、結構面白いです。 以上のような特徴により、Solidは今までWebアプリケーションの背後にあったユーザのデータを、別の場所(=POD)に切り離して管理できるようにします。 そしてこのSolidを単なる理想論から現実に近づける特徴が「標準化された技術でできている」ことです。 Solidは大雑把に言って2つの標準を使用しています。まず1つがWebIDです。ユーザは自由にPODを乗り換えることができますが、ユーザがPODを変えてもユーザのデータのURLは変えない仕組みと言えます。1 そしてもう1つがRDFです。これはアプリケーション間のデータの形式の差異の最小限にするためのものです。GoogleカレンダーがPODに正しく予定を保存してくれていれば、その情報がYahoo! カレンダーでもそのまま開けるということですね。 なるほど… ではこのSolidをTRPGのキャラクターシート置き場に利用すると、何が起こるのでしょうか。 キャラクターシートをSolid PODに保存すると何が起こるか 「キャラクターシート置き場にSolidを利用する」ということは「キャラクターシートをSolid PODに保存する」ことを意味します。 こうすることで何がどうなるのか、もしすべてのサービスがSolidに対応していたと仮定して、使い方をシュミレートしてみたいと思います。 まず、ユーザはキャラクターシートを作成するために「クトゥルフWebダイス」さんのようなサイトでダイスを振り、能力値を決めます。ついでに技能値やキャラクター名も決めたところで保存ボタンを押すと、Solid PODに保存されます。 ユーザはそのまま好きなオンセサイトに移動すると「PODに保存されたキャラクターシート一覧」が更新され、先程作ったものが選べるようになっています。 こんな感じです。書き込みも読み取りも、初回はWebIDの入力と権限の確認があるでしょう。 データとアプリケーションが粗結合になったことでそれぞれのサービスの相互の対応の可否を気にする必要がなくなりましたし、開発者としてもSolidのみに対応することでよくなりました。 また今までは、例えばオンセなどでは「外部サービスからのインポート」と「自サービスのDBからの読み出し」を別の機能として実装していたのが、「Solidからの読み出し/保存」に統一されることで開発の負担も減ることが予想されます2。 更にSolidはリアルタイム更新対応です3。 そしてそしてすべての情報は予め定まった「キャラクターシートの規格」に沿って保存されるため、他のどんなアプリケーションでも同様にデータを認識することができ、ユーザは好きなサービスに乗り換えやすくなることでしょう。

git push origin masterを絶対に手打ちしないために

この記事はAizu Advent Calendar 2018の10日目の記事です。 雰囲気でシェルをやっているクソザコです。 $ git push fatal: The current branch master has no upstream branch. To push the current branch and set the remote as upstream, use git push --set-upstream origin master 初回にgit pushを打つとこのようなエラーが出ますよね。このメッセージどおり git push --set-upstream origin master と打てば二回以降は origin/master をデフォルトとして扱ってくれます。 が、Gitの言うがままにタイプしていては、リーナス・トーバルズに負けたということになってしまいます。 そこで自分はこんな感じにプロンプトを出すようにして今の所満足しています。 —追記— git push origin HEADでローカルブランチと同じ名前のリモートブランチにpushできるよ! -uのときも使える — そな太@GraphQLの記事を書くぞ (@sonatard) December 21, 2018 まじで!? と思ってドキュメントを確認したら本当に書いてあった。 なんというか、HEADはローカルのリビジョンを指すときのみに使用できるイメージがあったので、これには驚きだった。 ちゃんとこんなふうに書いても動く。 git push origin HEAD:HEAD ちなみにちなみにHEADの内容をそのまま展開しても動く。 $ cat .

てすと

てすてす

Go の新しい Generics のデザインはなぜこんなに「歪」なのか Go の新しい Generics のデザインが出ました。 https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md 興味深い点が多くあるので原文を読むことをおすすめしますが、ざっくり言うと以下のような構文によって型パラメータが導入されることになります。 type Float interface { type float32, float64 } func Sqrt(type T Float)(v T) T { ... } 一見すると2019年の Contracts のデザインよりもすっきりし、他のジェネリクスがある言語のように直感的になったように見えますが、実は他の言語と同じように考えているとハマりそうな落とし穴があります。そこには Go ならではの事情があるのですが、今日はそのあたりの話をします。 interface と contracts が統合されたわけではない 表面的には contract という予約語は消え、interface と同一の存在になったように見えますが、実はそんなことはありません。 例えば以下のようなコードが例としてデザインドキュメントに示されています。 type integer interface { type int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr } func Add10(type T integer)(s []T) { for i, v := range s { s[i] = v + 10 } } type int, .