あんパン

こしあん派

1秒おきになんかする

ちょっと前の話だけど、社内のISUCON練習会で特定のエンドポイントが重いのをなんとかしようとしていた。このエンドポイントはキャッシュして問題ないので普段はキャッシュから返して1秒おきにリフレッシュしたい。Redisなどに入れてTTLを指定してキャッシュが揮発していたら再生成という手もあるが、これだとTTLが切れた瞬間わずかにリクエストが詰まってしまう。なので、何か別の手立てで定期的にキャッシュをリフレッシュしたい。

Goだとcarlescere/schedulerを使えば簡単にできそう。ただ、この回はPerlでやろうということで進めていた。AnyEventを使えばなんとかなる? と思いつつあんまり慣れていないライブラリを突然使うのはコストが高い。そんなときwatchを使えばいいじゃんということに気付いた。

systemdのunitファイルを以下のような感じで書いて systemctl start すれば良い。watchで1秒おきにcurlを起動してキャッシュの再生成エンドポイントを叩く作戦。

[Unit]
Description=Refresh cache every second

[Service]
Type=simple
Environment=TERM=linux
ExecStart=watch -n1 "curl -s http://localhost/refresh-cache"

[Install]
WantedBy=multi-user.target

watchはcurses的なやつが起動するので、 Environment=TERM=linux しておかないと Error opening terminal: unknown. というエラーが出る。

ところでsystemdにはtimerがあり、これも秒ごとに実行することができる。あとで思い出して試したところ、タイマーの精度が悪いのか実行が抜け落ちてしまうことがあった(AccuracySec=1us とかにしてもだめだった、なんででしょうね)。ということでwatchくらいが手軽でよさそうではないか。なかなか使うこともないだろうけれどメモ。


追記(2022-08-09):

1秒おきになんかする - あんパン

while true; do sleep 1; curl ….; doneとかはどうでしょう

2022/08/06 01:40
b.hatena.ne.jp

確かにwhileで回すのも良さそうですね。結果が標準出力に出るのでjournalctlなどで様子を観察しやすいのも良さそう。

技術書は出版社の直販サイトでPDFを買っている

よくKindleでセールやってる! 50%オフ! 50%ポイント還元! ということがあるけれど、全部無視して出版社のサイトでPDFを購入している。

  • DRMがかかっていない
    • メールアドレスがPDFのページに刻印されたりはある
  • 好きなリーダーで読める
    • 自分の管理方法は後述
  • 出版社に一番還元できる
    • と勝手に思っている

あたりが理由。

購入できるサイト

あとは技術書典やBoothなどには同人系もありそう。

逆に購入できないところで大手だとMdNとかSBクリエイティブなどがある。これらはKindleで購入するしかない。自分はKindleで買うのはいやだなと思って紙で買っている…… (しかしマンガはだいたいKindleで買っている)

どう読むか

Google Driveに入れてiPadのAcrobat ReaderにGoogleアカウントを紐付けて読んでいる。

iPad miniでリストを表示した様子

なぜAcrobat Readerかというと

  • 下手なリーダーよりはAcrobat Readerの方が使いやすい
    • 純正なので
    • 一応自分で注釈入れたりもできるけどあんまり使ってない。気になったところはプライベートのScrapboxに転記している
  • Acrobat ReaderにはGoogle Drive連携があり、Google Driveに放り込んでおけば自動で同期される
    • Dropbox連携もあるのでDropbox派の人はそれでもOK
  • Acrobat Reader自体はiOSでもAndroidでも配布されているので、iPadでもAndroidタブレットでもだいたい同じ体験で読める
    • ただし、Google Drive連携はGoogle Play 開発者サービスが存在しないAndroidタブレットでは利用できない
      • Kindle Fire系のタブレットでは利用できなかった
      • BOOXでは利用できた

という意図。他の人の暮らしも知りたい。

node_modules以下に依存をインストールしない状態でnpm outdated --json --longを実行するとcurrentパラメータが存在しない状態で出力される

拙作の yarn-outdated-formatter にIssueが建てられたので眺めたところ発見しました(社のSlackで共有したところ id:mizdra さんに確かめていただきました。ありがとうございます:pray:)。

github.com

package.json に書かれているバージョンが必ずしもインストールされるバージョンではないので現在インストールされている依存のバージョンが表示されないのは自明といえば自明ですね。その他にも、依存の package.json に含まれている homepage 情報も欠けるようでした。

この記事を書いてる時点で最新の npm/clilib/commands/outdated.js を眺めてみると確かに currentundefined になるケースは存在しそう。

github.com

ところでこの node はNode.jsの node ではなくて、 node_modules を木構造で管理する @npmcli/arboristnode (グラフにおけるノード) なんですね。

node.package The contents of this node's package.json file. https://www.npmjs.com/package/@npmcli/arborist

ejje.weblio.jp

ネーミングがおしゃれ。

これまで npm/cli のコードを読んだことはなかったのですが、結構細かくモジュールが分割されていて面白いですね。

自作のgitサブコマンドをzshで補完する

普段の暮らしでは自作のgitサブコマンドを作って便利に使っている。

masawada.hatenablog.jp

masawada.hatenablog.jp

のだけど、通常そのままではzshの補完が効かず、全て打つかhistoryから呼び出すかする必要があった。不便だしさすがに何か方法あるだろうな〜と探っていたところ発見したのでご紹介。

A better solution is to create a function _git-foo() to handle specific completion for that command. This also allows you to add command-specific completion as well. Place such a function inside an autoloaded #compdef file and you should be all set. You can add a description to such a function by adding a line matching

#description DESCRIPTION

as the second line in the file. See Completion/Debian/Command/_git-buildpackage in the Zsh sources for an example.

zsh/_git at master · zsh-users/zsh · GitHub

ふむふむ。つまり、通常の補完ファイルと同様に _git-foo のような命名でファイルを置くとよいとのこと。詳しくは Completion/Debian/Command/_git-buildpackage を見ると分かりそう。

#compdef git-buildpackage
#description build Debian packages from a git repository

_arguments \
  '--version[show program version number and exit]' \
  '--help[show help message and exit]' \
  '--git-ignore-new[build with uncommitted changes in the source tree]' \
...

zsh/_git-buildpackage at master · zsh-users/zsh · GitHub

なるほど2行目に #description を書くと補完時に表示されるようだった。_arguments を使えば引数の補完もできる。

補完のファイルは $fpath に列挙されているパスに存在している必要がある。自分は $HOME/.zsh/completion に置くことにした。

fpath=($HOME/.zsh/completion $fpath)
autoload -Uz compinit && compinit

これで試しに $HOME/.zsh/completion/_git-delete-branches を置くと…

$ git de
delete-branches - Delete selected branches (peco required)
describe        - show most recent tag that is reachable from a commit

動いた! ずっと不便だな〜と思っていたのではやいところやっておけばよかった。

CloudFrontにLambda@EdgeでBasic認証をかけて、originのS3にファイルを追加したらSlackにURLを通知する

この記事で書いたとおり、CloudFrontにLambda@EdgeでBasic認証をかけて、originのS3にファイルを追加したらSlackにURLを通知する仕組みを整えた。

github.com

repoをcloneしてきてCDKでdeployしたら同じ環境を作ることができる。

@aws-cdk/aws-lambda-nodejs はこれまで使ったことなかったのだけど、parcelでバンドルとかうまくやってくれて、 .ts ファイルをポン置きするだけでLambdaにデプロイしてくれて最高に便利。JSだと依存の管理がムズいしGoで書くのがいいかな〜となってGoでちまちま書くことが多かったけど、何も考えずにTypeScriptで書くでもよくなったことで手札が増えて嬉しい。

Basic認証は最初はCloudFront Functionsを使ってみようかと思っていたのだけど、結構制約が厳しそうなのでLambda@Edgeにした。Lambda@Edgeを明示的に使ったのは初めて(Next.jsをAmplifyでSSRしたときに暗黙的には使ってはいた)で、Lambda@Edgeも環境変数渡せなかったりとかいろいろ制約あるんだな〜ということを学んだ。CloudFront Functionsはこれ。

aws.amazon.com

今回はISUCONで便利に使ったけど、結構汎用的に使えるはずなのでよければどうぞ。