Hi, I’m lunarxlark

I ❤ ⌨. crkbd user.

gin + gorm v2でのセッションやトランザクション

TL;DR ginでの各リクエストを1セッションで管理しつつ、トランザクションも管理したい。 ginのmiddlewareで、gin.Contextにgorm.WithContextを用いてGormのセッションを持たせる。 ginの各HandlerFuncの中では、gin.Context内のGormセッションからDBへアクセスする。 モチベーション Gormはv2になり色々と変わった。 Gorm 2.0 Release Note 色々な記事が書かれているがTransactoinに関してあまり書かれていない。 下記疑問を払拭して正しい使い方を自分なりに確かめたかったので試した。 なんとなく動くがこれで正しいのか? ドキュメントを読んでいてSkipDefaultTransaction:trueだと30%もパフォーマンスが上がるというがその設定はtrueにしていいいのか? っていうか、DefaultTransactionって何?ロールバックの単位とかどうやって指定するの? 確認&検証 検証時に作成したソースはgithub.com/lunarxlark/gorm2-tx Context Gorm 2.0 #Context GormはContextサポートを提供し、それを使いたかったらWithContext使ってくれ。 また、Sessionには単セッションモードと継続セッションモードがある。 普通は、継続セッションモードを使って、複数オペレーションをまとめるよ。 …GormのSessionってどんなことできるの? Session Gorm 2.0 #Session Gormは`Session`メソッドをを通して、新しいセッションを提供するよ。 新しいセッションを作る場合、設定がたくさんあるよ。DryRunやLoggerとかね。 …新しいセッションを一々作るのは望んでない。 Contextサポートしてくれるってことなのでgin.Contextへ埋め込む時にセッションを作成してそれを使い回したい。 gorm.WithContextのreturnはdb.Sessionとなっている(下記はgormのソースから抜粋)ので、gin.Contextへ埋め込むだけで新たにセッションを作る必要はない。 1 2 3 4 // WithContext change current instance db's context to ctx func (db *DB) WithContext(ctx context.Context) *DB { return db.Session(&Session{Context: ctx}) } ここまでで下記みたいな感じになる。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 func main() { //....

September 12, 2021 · 2 分

ISUCON11予選に参加して惨敗した

結果 ISUCON 経験者の 2 名(@Aki_Mineo, @annkara)に誘われてチーム:コバミネとして参加しました。 私は主にインフラ担当でしたが、業務でバックエンドを Go で書いているためインフラの作業を終え次第、合流する作戦でした。 結果は 151 位 29614 点 でした。 悔しい。あそこで気付いていれば…みたいなポイントがクリティカルでした。 反省点 直すところはたくさんあったと思いますが、直すと決断するまでに迷いがありました。 時間内でのアプリケーションへの理解が足りなかった。 ユーザストーリの理解と加点の仕組みが結びつかなかった。 アプリケーションのどこを直したらいいか。 どう直したら加点されるのか。 非効率なポイントがあっても、他の要因ですぐに直せなそうだった。 見つけた時には時間が足りなかった。 修正して試す環境が本番環境のみだった。 大幅な修正をして、他メンバーとコンフリクトが起きるのが怖かった。 ざっくりタイムライン 前準備 private な作業リポジトリ(メンバーを招待) Discord との webhook deploy.sh 各種 tool のインストールスクリプト 10:00 競技スタート。 @annkaraが AWS アカウントを準備してくれたので CFn でスタック作成。 CFn でのインフラ作成完了。 ssh config 配布。全員が接続確認完了。 初回ベンチ回す。ベンチ:2981点 ソースや設定を GitHub へ。 conditionLimit : 20 -> 40。ベンチ:1704点(すぐ Revert) alp, netdata, pt-query-digest をインストール。 11:00...

August 22, 2021 · 1 分

EC2へssh with GitHubに登録している公開鍵

isuconの練習時にGitHubに登録している公開鍵でEC2へssh出来るように、userdataを設定したかった。 sedでのエスケープの仕方でハマったのでメモ。 #!/bin/bash su isucon -c 'mkdir -p /home/isucon/.ssh && touch /home/isucon/.ssh/authorized_keys' su isucon -c "curl https://api.github.com/users/{{github_user_id}}/keys | grep \"key\" | sed -e 's/ \"key\": \"//g' -e 's/\"//g' >> /home/isucon/.ssh/authorized_keys"

July 4, 2021 · 1 分

2021年版 vim + goplsの設定

goplsが出てから, vimでも定義ジャンプやシンボル検索、ドキュメント参照等が行えるようになった。 たまにVSCodeを触りvimでの作業を改善できないか考える中で、自身の設定が古いことに気付いた。また、ググってもなかなか出てこなかったのでメモとして記述する。 cf. GitHub dotfiles いきなりだが、vimrcとvim-lsp-settings/settings.jsonを抜粋して貼り付ける。 以前、GoではLspCodeAction, LspCodeLens等をサポートしていなかったが、今では使えるようになっている。 キーマップに設定している関数は全てGoで使用出来る。 ただし、カーソルがどこにいても実行出来るわけではないので注意が必要。 LspCodeActionはカーソルの位置によって実行内容が変わるのでそこも注意。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 ...Plug 'prabirshrestha/vim-lsp'Plug 'mattn/vim-lsp-settings'Plug 'prabirshrestha/asyncomplete-lsp.vim'Plug 'mattn/vim-gomod'..." ------------------------------------------------------------------------------" vim-lsp" ------------------------------------------------------------------------------function! s:on_lsp_buffer_enabled() abort setlocal omnifunc=lsp#complete setlocal signcolumn=yes if exists('+tagfunc') | setlocal tagfunc=lsp#tagfunc | endif nmap <buffer> <leader>ac <plug>(lsp-code-action) nmap <buffer> <leader>cl <plug>(lsp-code-lens) nmap <buffer> <leader>df <plug>(lsp-definition) nmap <buffer> <leader>dd <plug>(lsp-document-diagnostics) nmap <buffer> <leader>im <plug>(lsp-implementation) nmap <buffer> <leader>pdf <plug>(lsp-peek-definition) nmap <buffer> <leader>sm <plug>(lsp-document-symbol-search) nmap <buffer> <leader>Sm <plug>(lsp-workspace-symbol-search) nmap <buffer> <leader>rf <plug>(lsp-references) nmap <buffer> <leader>td <plug>(lsp-type-definition) nmap <buffer> <leader>rn <plug>(lsp-rename) nmap <buffer> <leader>en <plug>(lsp-next-error) nmap <buffer> <leader>ep <plug>(lsp-previous-error) nmap <buffer> <leader>ho <plug>(lsp-hover) let g:lsp_format_sync_timeout = 500 autocmd!...

June 16, 2021 · 2 分

load test with dynamic payload by tsenart/vegeta

負荷テストツールvegetaのコマンドでの使い方ぐはググるとたくさん出てくるが、ライブラリとして仕様している記事が少なく手こずったのでメモ代わりに記事にする。 やりたいこと リクエスト毎にRequestの内容を動的に変えて、負荷をかけたかった。 Headerに持つタイムスタンプがリクエスト時のタイムスタンプになるように。 userIdはuniqueになるように。(同じユーザだと重複リクエストを弾く処理があったため。) 具体的には下記のような感じでリクエストを送りたい。 1 2 3 4 5 {"header": {"timestamp":"1234"}, "body": {"userId": "lunar-1"}} {"header": {"timestamp":"1234"}, "body": {"userId": "lunar-2"}} {"header": {"timestamp":"1235"}, "body": {"userId": "lunar-3"}} ... {"header": {"timestamp":"1240"}, "body": {"userId": "lunar-n"}} vegeta.Targeterは func(*vegeta.Target) error である。 また、vegeta.Attackは、vegeta.Targeterをgoroutineで都度呼び出して、Targeter内からTargetに基づきリクエストしていることから、都度Targetが変わるようなTargeterを返す関数を作成し、それをAttack時に呼び出せば良さそう。 ってことが、 [QUESTION] Sending requests with dynamic body #330に書いてあって何度も行き来した結果やっと理解できた…。 上記を拝借して以下のようにすることで目的を達成できた。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 type yourRequestBody struct { UserID string } targeter := func(id uint64) vegeta....

March 11, 2021 · 1 分

2020年 ふりかえり

2020年の振り返りと来年にやりたいことをつらつらと書こうと思う。 きっかけは、1on1をしてくれたEMからのアドバイスだ。 年末になると、1年を振り返るが過小評価しがち 何回かに分けてやると良い 謙遜せずやったことはやったと自分に言う そんな趣旨のアドバイスを貰った。実際、いつも自分でやる振り返りでは、今年も結局…みたいな評価になってしまっている。 仕事を頑張っていないわけではない。今年は自分でも頑張ったと思う。そんな、いつもは謙虚な(?)な自分に今年は前向きな評価をしてあげよう。 そう思った。 Dependency Injectionの実装方法を理解した トランザクションマネージャ(DB参照先を捕捉し、rollbackを埋め込んであるmethodを持つinterface)を依存性に注入することでrollback記載不要に。 トップダウンで記述するDIでは、DB参照先もあらかじめ記述しておけるが、トランザクション範囲については自身で記載しなければ出来ないという結論に。 ポインタレシーバにはポインタが、値レシーバには値がコピーされる。 メソッドをinterfaceに指定する際、レシーバにコピーされる値への変更を保持したいか等でポインタ/値レシーバどちらにするかの判断基準になる。 WebFramework Echoのmiddlewareの作り方。 Skipperによるecho.Contextの使い回し方。(structメンバーに、echo.Contextを引数に持つ関数を持たせる) Echoのデフォルトログでは、ヘッダーx-request-idに指定した値がrequest idに出る。 Echoのmiddlewareに対する理解が深まった。(雑) CloudFrontの各項目に対する理解が深まり、通信障害時にどのように調べて、どのメトリクスを見れば良いかがある程度わかるようになった。 CloudFrontのrequest idをoriginのEchoへ出力したい場合、x-amz-cf-idをEchoロガーで出力すればよい。 L@Eの使い方と開発/リリース時の注意点について教訓を得た。 L@Eへの反映には時間がかかるので、テストの仕方を工夫しなければいけない。 L@Eに適用するLambdaのversionはLATESTを指定出来ないので、リリース時にはLambdaのversionを数値指定しなければいけない。 L@Eを修正するにあたり、Node.js v10.xを少し勉強した。(動的型付け言語は好きになれない。結局、undefinedと向き合わなければならず、動的型付けのメリットが感じられなかった。) その点、TypeScriptはちょっと触った感じ楽しかった。トランスパイルという言葉を知った。(言語のversionがどんどん上がっていくECMAScriptに対して、トランスパイルが追従していけるのかちょっと不安を感じた。) AWS StepFunctionは、Lambdaをjsonというインタフェースで繋げていて、Lambdaのフローをjsonで定義しているだけなんだと理解した。 AWS Lambdaをローカルである程度動作確認出来るようにDEBUGフラグを付けた。 Go言語の開発環境が自分の中で固まってきた。(Vimで必要なPluginがある程度固定されてきた) Alfredにより、unixtimestamp変換とbase64エンコード/デコードが素早く行えるようになった。 CI/CD時にdocker pull rate limitによるエラーを、DockerHubへのログインで解消させた。 コネクションプールの生存時間が短すぎることを見つけ、DBstatsからコネクションスパイクに対してプール生存時間を伸ばすことでDBへの負荷とコネクション接続時のlatencyを短くした。

December 29, 2020 · 1 分

Custome Logger using LoggerWithConfig in Echo

WebFramework EchoのLoggerを弄っていて気付いた点があったのでメモ。 sample code 箇条書き responseログにHeader X-Any-Headerを出力したい場合、ログフォーマットに"any_header":${header:x-any-header}を指定すればいいよ responseログにQueryParamerter ?anyparam=xxxを出力したい場合、ログフォーマットに"any_query":${query:anyparam}を指定すればいいよ デフォルトで出力されるカラム’id’はHeader X-Request-Id を指定すると出力されるよ Skipperを設定することで、path毎にログ出力する/しない等を設定出来るよ 1, 2, 3はEchoのそういう機能だってことで特にありません。 4は結構便利だなと思いました。以下のサンプルコードでは、/healthcheckに来た場合とCI/CD等での自動テスト時にはresponseログを出力しないようにする設定例です。 sample 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 // Middleware e....

November 10, 2020 · 2 分

自分用日本語訳 Go Module

(この記事は、執筆時点でのGo Modulesをもとにした私のメモです。Go Moduleの理解のために、元記事と記載の順番が入れ替わっている項目もあります。) ...

May 14, 2020 · 2 分

New Github Official CLI `gh`

github.com/cli/cli/cmd/gh is new official command for GitHub. ...

February 14, 2020 · 1 分

From denite.nvim To fzf.vim

denite.nvimとfzf.vimって比較記事? 違います。断捨離した結果、fzf.vimで事足りてしまったという記事です。 denite.nvimとfzf.vimは、一見やれることが似ているように見えますが提供しているインタフェースが違います。 denite.nvimの方が拡張性/汎用性が高いです。Pythonスクリプトを呼び出せますし。 どうしてやめたん? Python3とpipの環境整備に疲れたというのが理由で完全に力不足なだけです。 そもそも使いこなせていなかったっていうのも大きい。自分に必要な機能が何か見直したら次のがあれば十分っぽい。 コマンドの結果の一覧表示(x-motemen/ghq list, mattn/memo list, history等) 一覧表示の後のアクションを指定可能(cd, vim) buffer切替 fzf.vimはfzfのついでに入れていただけで全く使っていなかった。Shougo/denite.nvimでfzf.vimで同じことが出来るし、sourceの拡張がいくつもあるのでそれで十分だった。 もともとfzfが好きなのもあって、fzf.vimで上記が実現出来るように設定した、っていうかhelpからパクってきた。 何日か使っていて快適に使えているので結構満足。previewはbatってコマンド入れないとsyntax highlightされなかったのでいれたけど、なんとなくそっちの方がリッチっぽいという理由だけなので重ければそのうち消す。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 command! -bang -nargs=? -complete=dir Files call fzf#vim#files( \ <q-args>, \ fzf#vim#with_preview(), \ <bang>0)command!...

February 11, 2020 · 1 分