feat: メンション対象の通知を別の投稿に分けて送る - #122
Merged
Merged
Conversation
メンション対象の通知を投稿単位で見分けられるようにするため、送信先に依存しない 重要度フラグ important を Notify::Message に追加する(issue #120)。 判定は reason だけで行い、CI によるメンション抑止(issue #105)は反映しない。 抑止は「レビューできない PR でチャンネル全体を叩かない」ためのもので、通知の 重要度を下げるものではない。両者を同じフラグにすると、CI が赤いレビュー依頼が 通常の通知に混ざってしまう。 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SmoDC7XRgDx1AcWumgv3Uq
メンション対象とそれ以外が同じ投稿に混ざると、`@channel` が付いていても、 どれが自分宛てなのかは投稿を開くまで分からない。important? が切り替わる位置で 投稿を区切り、`@channel` の付く投稿には自分宛ての通知だけを入れる(issue #120)。 区切るのは並べ替えではなく分割なので、通知は updated_at 昇順のまま送られる。 既読化は「送信済みは常に先頭からのプレフィックス」であることに依存しているため (issue #94 / #100)、この順序は保つ必要がある。区間ごとの yield には直前までの 区間の合計を足し、既読化に渡る累計を分割前と一致させる。 送信先アダプタを包むデコレータにする案は、委譲先の静的型にデコレータ自身が 含まれ、yield するブロックのインライン展開が無限再帰してコンパイルできないため 採らない。累計の正しさは既読化の境界と表裏なので、mark_read_through と同じ場所に 置く。 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SmoDC7XRgDx1AcWumgv3Uq
メンション対象の通知を別の投稿に分けるようになったため、その挙動と、時系列を 維持すること、区切りの判定に reason だけを使うことを README に追記する (issue #120)。あわせて、既存の CI によるメンション抑止(issue #105)も メンション節に書き足す。 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SmoDC7XRgDx1AcWumgv3Uq
ameba の Style/VerboseBlock 指摘に対応する。
`{ |usecase| usecase.check_notifications }` を `&.check_notifications` にする。
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmoDC7XRgDx1AcWumgv3Uq
limit7412
marked this pull request as ready for review
August 29, 2026 05:43
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ccc000f29f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Slack::PostRepository は応答を捨てていたため、429 や 5xx で投稿されなかった 場合でも累計件数を yield し、呼び出し側がその通知を既読化していた。 表示されないまま消える通知が出るため、失敗は例外にして既読化を止める。 重要度で投稿を分けるようになり(issue #120)、1 実行あたりの投稿数が増えて レート制限に当たりやすくなった。一時的な失敗でその実行を丸ごと落とさずに済む よう、429 と 5xx は Retry-After に従って再送する。方針と定数は既存の Discord::PostRepository に揃えた。 送信部を post_json に切り出し、spec では HTTP を張らずに応答を差し替える。 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SmoDC7XRgDx1AcWumgv3Uq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
issue #120 の案C(同一チャンネルへの分割投稿、時系列は維持)の実装。
やったこと
メンション対象の通知とそれ以外を、別々の投稿に分けて送るようにした。
両者が同じ投稿に混ざると、
@channelが付いていても、どれが自分宛てなのかは投稿を開くまで分からない。important?が切り替わる位置で投稿を区切ることで、@channelの付く投稿には自分宛ての通知だけが入る。古い順に「通常・メンション・メンション・通常」と届いた実行なら、投稿は「通常 1 件」「メンション 2 件」「通常 1 件」の 3 つになる。
チャンネル上の並びは従来どおり時系列で、投稿の境界だけが増える。
変更点
Notify::Message#important?を追加した(1 コミット目)送信先に依存しない重要度フラグを持たせ、
Github::Usecase#build_messageで設定する。判定は reason だけで行い、CI によるメンション抑止(#105)は反映しない。
抑止は「レビューできない PR でチャンネル全体を叩かない」ためのもので、通知の重要度を下げるものではない。
両者を同じフラグにすると、CI が赤いレビュー依頼が通常の通知に混ざってしまう。
結果として、CI が赤い PR では
@channelだけが従来どおり抑止され、投稿はメンション対象側に入る。Notify::Usecase#send_splitを追加した(2 コミット目)important?が同じ値で連続する区間ごとに、アダプタのsend_messagesを呼ぶ。区切るのは並べ替えではなく分割なので、通知は updated_at 昇順のまま送られる。
既読化は「送信済みは常に先頭からのプレフィックス」であることに依存しているため(#94 / #100)、この順序は保つ必要がある。
区間ごとの yield には直前までの区間の合計を足し、既読化に渡る累計を分割前と一致させている。
README を更新した(3 コミット目)
投稿の分割と、あわせて既存の CI によるメンション抑止(#105)をメンション節に書き足した。
Slack の webhook 応答を検査するようにした(5 コミット目)
Slack::PostRepository#send_postが@client.postの戻り値を捨てていたため、429 や 5xx で投稿されなかった場合でもyield messages.sizeに進み、呼び出し側がその通知を既読化していた。表示されないまま消える通知が出るので、失敗は例外にして既読化を止める。
バグ自体は以前からあったが、重要度で投稿を分けたことで 1 実行あたりの投稿数が増え、レート制限に当たりやすくなった。
一時的な失敗でその実行を丸ごと落とさずに済むよう、429 と 5xx は
Retry-Afterに従って再送する。待機上限(5 秒)と試行回数(3 回)を含め、方針と定数は既存の
Discord::PostRepositoryに揃えた。再送ロジックが Slack と Discord で重複した。
共通化は notify 層に HTTP の知識を持ち込むか新しい抽象を足すことになり、この PR のスコープを広げるため見送っている(#123)。
プランからの変更
issue のプランでは
Notify::SplitPostRepositoryというデコレータをnotify層に足し、main.crで既存の poster を包む形にしていた。これはコンパイルできなかったため、
Notify::Usecaseに置く形に変えている。デコレータは自身も
Notify::PostRepositoryなので、委譲先@posterの静的型にデコレータ自身が含まれる。Crystal は yield するブロックを常にインライン展開するため、
@poster.send_messages(run) { yield ... }の展開が無限再帰する(Error: recursive block expansion)。ブロックを Proc として捕捉する形も試したが、同一の仮想呼び出しに yield 版と捕捉版の実装が混在することになり、これも通らなかった。
置き場所としても、累計の正しさは既読化の境界と表裏なので、
mark_read_throughと同じファイルにあるほうが不変条件を一箇所で追える。環境変数の追加も
main.crの変更も不要になった。影響範囲
@everyoneはメンション対象の区間のチャンクにだけ付くようになり、従来(チャンク内に 1 件でもあれば付く)より正確になる。Error::Usecase)はsend_messageで 1 件ずつ送るため分割の影響を受けない。ただし Slack の応答検査は効くので、これまで握りつぶしていた送信失敗が例外になる。テスト
crystal specは 119 examples, 0 failures。追加したのは以下。投稿の分割(
spec/notify/usecase_spec.cr,spec/github/usecase_spec.cr)Slack の応答検査(
spec/slack/repository_spec.cr)送信部を
post_jsonに切り出し、HTTP を張らずに応答を差し替えている。修正前の実装(応答を捨てる)に戻すとこのうち 4 件が落ちることを確認した。
検証環境について
この環境ではネットワーク制限により Crystal 1.21.0 を用意できず、Ubuntu の 1.11.2 で検証している。
1.11 ではフォーマッタが複数行引数の末尾カンマを落とすためリポジトリ全体に差分が出る。
crystal tool formatは実行せず、追加分だけを既存の記法に手で合わせた(CI の--checkで確認済み)。ameba は 1.11 でビルドできずローカル実行できなかったため、初回の CI で
Style/VerboseBlockの指摘を受けて 4 コミット目で直している。Closes #120