私が歌川です

@utgwkk が書いている

ChatGPT日記

「足の血行がよくない気がするので、ヨドバシ.comで養命酒を注文した」という内容の日記を書いてください。文体は「だ・である」調にしてください。


先日、足の血行がよくない気がすると感じたので、健康ドリンクの養命酒をヨドバシ.comで注文することにしました。

私は普段から健康に気を遣っており、特に最近は運動不足やストレスがたまっているため、体調管理に力を入れています。そこで、養命酒の効果を耳にして以来、興味を持っていました。

実際に飲んでみる前に、ヨドバシ.comで商品情報を確認し、口コミや評価を参考にしました。その結果、養命酒は健康維持に効果があるとの声が多く、信頼できる商品であると判断しました。

注文は簡単で、サイト上で商品を選択して、配送先や支払い方法を入力するだけでした。商品が届くのも早く、手軽に購入できたので、とても便利でした。

今後も健康に気を遣いながら、養命酒を飲み続けて、体調を整えていきたいと思います。


ありがとうございます。後出しになってしまい申し訳ないのですが、いくつか事実と異なるため、訂正してもらいたいです。

  1. 私は普段それほど健康には気を遣っていません。
  2. 養命酒はまだ届いていません。明日には届く予定です。

申し訳ありません。以下、訂正版をご確認ください。

先日、足の血行がよくない気がすると感じたので、健康ドリンクの養命酒をヨドバシ.comで注文することにしました。

私は普段それほど健康には気を遣っていませんが、最近は運動不足やストレスがたまっているため、体調管理に力を入れています。そこで、養命酒の効果を耳にして以来、興味を持っていました。

実際に飲んでみる前に、ヨドバシ.comで商品情報を確認し、口コミや評価を参考にしました。その結果、養命酒は健康維持に効果があるとの声が多く、信頼できる商品であると判断しました。

注文した養命酒はまだ届いていませんが、明日には届く予定です。注文は簡単で、サイト上で商品を選択して、配送先や支払い方法を入力するだけでした。商品が届くのも早く、手軽に購入できたので、とても便利でした。

今後も健康に気を遣いながら、養命酒を飲み続けて、体調を整えていきたいと思います。


初めてChatGPTを使ってみたけど、適当なプロンプトを入力するだけでそれらしい文章が出てきてすごい気がする。『文体は「だ・である」調にしてください』という指示が完全に無視されているし、訂正が場当たり的すぎる気がするけど、まあいいか。

有効期限を過ぎても消えないインメモリキャッシュの謎

tl;dr

キーワードは「monotonic clock」です。

あらすじ

Goで以下のようなコードを書いていた*1*2。あるAPIを叩くクライアントで、APIコールに必要なアクセストークンを4時間キャッシュしている。c.getToken() で得られたトークンを使ってAPIコールを行えばよい。

type Client struct {
  mu        sync.RWMutex
  expiresAt time.Time
  token     string
}

// トークンのキャッシュがあればキャッシュから返し、なければ更新してから返す
func (c *Client) getToken() string {
  if cachedToken, ok := c.getTokenFromCache(); ok {
    return cachedToken
  }

  return c.refreshToken()
}

// トークンをキャッシュから返す
// 有効なトークンがキャッシュされていたら (トークン, true) を返す
// 無効だったら (空文字列, false) を返す
func (c *Client) getTokenFromCache() (string, bool) {
  c.mu.RLock()
  defer c.mu.RUnlock()

  // time.Now() < c.expiresAt
  if c.token != "" && time.Now().Before(c.expiresAt) {
    return c.token, true
  }

  return "", false
}

// トークンを更新してキャッシュしてから返す
func (c *Client) refreshToken() string {
  c.mu.Lock()
  defer c.mu.Unlock()

  // 更新したトークンが token 変数に入っているとする
  // トークンをキャッシュに格納する
  c.token = token
  // 4時間で期限切れになる (実際にはもうちょっと短いものとして管理している)
  c.expiresAt = time.Now().Add(4 * time.Hour)
  return c.token
}

うまく動いていそうということでしばらく開発を続けていた。が、ある日、APIクライアントがうまく動いていないらしいという報告を受けた。手元の開発マシンでバックエンドのアプリケーションを立ち上げたまま終業し、始業してから作業を再開しようとすると、アプリケーションがエラーを返すようになる。アプリケーションを起動しなおすと直るらしい。

もらったログを見ると、どうやら無効なトークンを使いつづけているようだ。期限切れかどうかを判定するロジックがおかしいのか? 排他制御がうまくいっていないのか? と見直してみたけど一見よさそう。他のメンバーに動作確認してもらった範囲では、うまくトークンを更新できているようだった。

キャッシュの有効期限とキャッシュヒットしたかどうかをログに出力するようにしたら、現在時刻が有効期限を過ぎているのにキャッシュヒットしたという出力が得られた。なんなのか。分からないまま調査しているうちに、ふと見たらトークンが更新されてしまっていた……。

さて、一体何が起こっていたのだろうか?

*1:実際のコードとは異なり、大きく簡略化している

*2:このコードに致命的な不具合があると前提が大きく変わるので、あったらコッソリ教えてください

続きを読む

雑多な日記

ここ最近は凪のような暮らしをしている気がする。感情の起伏もあまりないので、何かが起こっていても、なんかやっているな~という感じで他人事のように眺めている。達観しているかどうかでいうと、どうなんでしょうか? めちゃくちゃに忙しくなったらまた変わるのかもしれない。ブルアカの4th PV*1が出た直後が一番たいへんだったと思うけど、それぐらいか?


数年ぶりに分散SNSブームが来ているけど、Mastodonに熱中しているわけでもなく、のんびり暮らしている。知り合いがそこにいてなんか喋っているのを眺めているぐらいで、分散SNS経由で新たな出会いを求めるとかそういうこともない。つまるところ、人間がどこに集まっているか、というのが最大の問題なのではないか。身内でDiscordで集まっているならDiscordでええやん、みたいな。Discordもそんなにちゃんと使ってないけど……。

いちおうTwitterアカウントでログインしているサービスを見直すところまではやった。


コカコーラゼロとオレンジジュースを混ぜたら、小学生の頃にドリンクバーで作った飲み物の味がした。


凝ったものを作って暮らしを便利にするのと、凝ったものばかりを作りたい誘惑とのバランスについて考えることがある。難しいことをやっているけど脱出は可能で、あると暮らしが便利になる、ぐらいのグッズを作っていて、単なる自己満足になっていないかは常に自問自答している。なぜ凝ったことをやるのか、それは最高の体験を提供したいから*2というのを忘れずにいたい。

あとは、難しい問題を解く技術のほかに、難しい問題を分解して複数の簡単な問題にして、スペシャリストじゃなくても解決しやすいようにする技術というのもあると思った。「魚の釣り方」のメタファーでいうと何?


3ヶ月遅れで、いい音が鳴りまくるMVに出会うのであった……。

www.youtube.com

YAPC::Kyoto 2023でトークします、直ちにチケットを買ってください

blog.yapcjapan.org

ということで、3/19に開催されるYAPC::Kyoto 2023でトークをします。タイトルは「prototype大全」です。

prototypeは、Perlのサブルーチンの引数の振る舞いを変える機能です。一見するとただの記号の並びに見えるprototypeですが、実は身近なところに潜んでいて、Perlプログラムを支えているのです。このトークでは、そんなprototypeについて魅力や活用法などを交じえながらお話しする予定です。

* try/catchから始めるprototype入門
* こんなにあるぞ!! prototype
* 気になるあのサブルーチンのprototype、コッソリ教えます
* prototypeを使う/使わない理由

見ての通り、なんとPerlの話が行われる予定です。すごいですね。

チケットの販売は1/31までです。忘れずにお買い求めください。

passmarket.yahoo.co.jp

www.youtube.com

余談