Skip to content

Notificationテーブルのスキーマ変更#22

Merged
kantacky merged 20 commits into
mainfrom
update-db-schema
Apr 28, 2026
Merged

Notificationテーブルのスキーマ変更#22
kantacky merged 20 commits into
mainfrom
update-db-schema

Conversation

@kantacky
Copy link
Copy Markdown
Member

@kantacky kantacky commented Apr 28, 2026

概要

Notification の通知済み状態を、Notification 単位の isNotified フラグから対象ユーザー単位の notifiedAt (NotificationTargetUser.notifiedAt) へ移行する。これに伴い OpenAPI スキーマ・生成コード・GORM モデル・ドメイン・リポジトリ・サービス・コンバータを一括で追従させる。

背景

  • 旧スキーマでは Notification 全体に対して isNotified を持っていたため、対象ユーザーごとの通知成功/未送信状態を表現できなかった。
  • dotto-typespec 側で Notification.targetUserIds / Notification.isNotified を廃止し、Notification.targetUsers (NotificationTargetUser { userId, notifiedAt }) で対象ユーザーと通知日時を管理する形に変更されたため、user-api 側を追従させる必要がある。

スキーマ仕様メモ

dotto-typespec の仕様に合わせ、リクエストとレスポンスでフィールド形が異なる点に注意:

  • レスポンス (Notification): targetUsers: NotificationTargetUser[]userIdnotifiedAt を保持)
  • リクエスト (NotificationRequest): targetUserIds: string[](作成・更新時はユーザーID配列のみ受け取り、notifiedAt はサーバー側で管理)

変更点

OpenAPI / 生成コード

  • openapi/openapi.yaml を最新の dotto-typespec 出力に更新し、レスポンスを targetUsers (NotificationTargetUser) 形式へ移行(リクエストは targetUserIds のまま)。
  • generated/api.gen.go を oapi-codegen で再生成。

データベース層 (internal/database)

  • database.Notification から IsNotified カラムを削除。
  • database.NotificationTargetUserNotifiedAt *time.Time を追加し、対象ユーザーごとに通知日時を保持する。

ドメイン層 (internal/domain)

  • domain.NotificationIsNotified / TargetUserIDs を廃止。
  • UserIDNotifiedAt を保持する domain.NotificationTargetUser を導入し、Notification.TargetUsers として扱う。

リポジトリ層 (internal/repository)

  • DispatchNotifications のシグネチャを「通知ID → 通知済みとして記録する UserID 集合」のマップ受け取りへ変更し、notification_target_users.notified_at を該当ユーザーに対してのみ更新するよう修正。
  • ListNotificationsisNotified フィルタを、notification_target_users.notified_at に対する EXISTS 句で表現。
  • UpdateNotification で対象ユーザー集合を入れ替える際、既存行の notified_at を保持したまま差分更新するよう修正。
  • 共通ユーティリティを internal/repository/util.go に追加。

サービス層 (internal/service)

  • notification_dispatch で未通知ユーザー (NotifiedAt が nil) のみを送信対象として抽出。
  • FCM 送信に成功したユーザーを per-notification で通知済みとして記録する。
  • 対象ユーザーに FCM トークンが 1 件も無い通知については、再ディスパッチの無限ループを防ぐため、対象ユーザー全員の notifiedAt を埋めて通知済み扱いとする(送信不能ユーザーの状態確定)。

ハンドラ層 (internal/handler)

  • toAPINotification をレスポンスの targetUsers 形式に合わせて変換。
  • toDomainNotification をリクエストの targetUserIds から domain.NotificationTargetUser を構築するよう修正。

確認事項

  • `go build ./...` が通ること
  • `go test ./...` が通ること
  • 通知作成・更新・一覧取得 API が新スキーマ(リクエスト `targetUserIds` / レスポンス `targetUsers`)で正しく動作すること
  • 通知ディスパッチで FCM 送信成功したユーザーの `notifiedAt` が記録され、送信失敗ユーザーは未通知のまま残ること
  • 対象ユーザーに FCM トークンが 1 件も無い通知は、対象ユーザー全員に `notifiedAt` が記録され、再ディスパッチ対象から外れること
  • `isNotified` クエリでのフィルタが、対象ユーザーの `notifiedAt` 状態に基づいて期待どおりに動作すること

kantacky and others added 4 commits April 28, 2026 10:06
Notification の targetUserIds/isNotified を targetUsers (NotificationTargetUser) に置き換えた openapi.yaml に合わせて、oapi-codegen で生成した API 型を再生成する。
API スキーマ変更に追従し、ドメインの TargetUserIDs を NotificationTargetUser のスライスへ変換するようにする。IsNotified フィールドは API から削除されたため出力しない。
OpenAPI スキーマで Notification.isNotified を廃止し
targetUsers[].notifiedAt で通知日時を管理する形へ変更されたため、
GORM モデル・ドメイン・リポジトリ・サービス・コンバータを追従させた。

- database.Notification の IsNotified カラムを削除し、
  database.NotificationTargetUser に NotifiedAt を追加
- domain.Notification の IsNotified / TargetUserIDs を廃止し、
  UserID と NotifiedAt を保持する domain.NotificationTargetUser を導入
- DispatchNotifications を通知ID→送信成功UserID のマップ受け取りに変更し、
  notification_target_users.notified_at を該当ユーザーに対して更新
- サービス層は未通知ユーザー(NotifiedAt が nil)のみを送信対象にし、
  送信成功したユーザーだけを per-notification で通知済みに記録
- ListNotifications の isNotified フィルタは
  notification_target_users の notified_at に対する EXISTS 句で表現
- UpdateNotification では既存行の notified_at を維持したまま
  対象ユーザー集合を入れ替え
- handler.toAPINotification / toDomainNotification を新スキーマに合わせて変換
従来は対象ユーザーのいずれか宛にトークンが存在すれば、FCM 送信結果に関わらず対象ユーザー全員を配信済みとして記録していた。
本コミットでは、トークンとユーザー ID の対応を保持し、SendEachForMulticast の応答からユーザー単位の成功可否を判定して、実際に配信に成功したユーザーのみを deliveries に積むよう変更した。
併せて FCM 呼び出し自体がエラーになった場合でも、その時点までに成功したユーザー分は確定保存する挙動に揃えている。
@kantacky kantacky marked this pull request as ready for review April 28, 2026 11:25
@kantacky kantacky requested review from a team, Copilot, hikaru-0602 and masaya-osuga April 28, 2026 11:25
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Notification の通知済み状態を Notification.isNotified から対象ユーザー単位の NotificationTargetUser.notifiedAt へ移行し、送信成功ユーザーのみを通知済みとして記録できるようにする変更です。

Changes:

  • ドメイン/DBモデルを TargetUsers + NotifiedAt へ移行(IsNotified 廃止)
  • ディスパッチ処理を「通知ID → 成功ユーザーID配列」の更新方式に変更
  • 一覧フィルタの isNotifiednotification_target_users.notified_at の状態で判定するSQLへ変更

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
internal/service/notification_dispatch.go 未通知ユーザーのみ送信対象にし、成功ユーザー単位で配達結果を収集
internal/service/notification.go リポジトリIFを deliveries map[notificationID][]userID 受け取りに変更
internal/repository/util.go NotificationTargetUser のユーザー重複排除ユーティリティ追加
internal/repository/notification_update.go ターゲットユーザー差し替え時に既存 notified_at を保持して再作成
internal/repository/notification_list.go isNotified フィルタを notified_at の EXISTS 条件で表現
internal/repository/notification_dispatch.go 送信成功ユーザーの notified_at を更新する実装へ変更
internal/repository/notification_create.go 作成時に TargetUsers をDBへ保存(NotifiedAt 含む)
internal/handler/converter.go API⇄ドメイン変換を targetUsers(レスポンス)へ追従
internal/domain/notification.go IsNotified/TargetUserIDs 廃止、TargetUsers[] 導入
internal/database/notification_target_user.go notification_target_users.notified_at カラム追加
internal/database/notification.go is_notified カラム削除、ToDomain/FromDomain を TargetUsers 対応

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/repository/notification_list.go Outdated
Comment thread internal/repository/notification_dispatch.go
Comment thread internal/handler/converter.go
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/service/notification_dispatch.go
Comment thread internal/repository/notification_update.go
Comment thread internal/repository/notification_dispatch.go Outdated
Copy link
Copy Markdown
Member

@masaya-osuga masaya-osuga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilotの新しいレビューも妥当そうな気がする

@kantacky
Copy link
Copy Markdown
Member Author

Copilotの新しいレビューも妥当そうな気がする

多分修正した

Dispatch 対象に FCM トークン保持ユーザーと未登録ユーザーが混在する場合、
従来は送信成功ユーザーのみ deliveries に積んでいたため、未登録ユーザーの
notified_at が更新されず再ディスパッチされ続けていた。送信成功ユーザー
に加えてトークン未登録ユーザーも delivered に含めるよう修正した。
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/repository/notification_dispatch.go
Comment thread internal/service/notification_dispatch.go
@kantacky kantacky disabled auto-merge April 28, 2026 12:18
Copy link
Copy Markdown
Member

@masaya-osuga masaya-osuga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilotの指摘直してもいいと思うけど、ほぼ問題ないと思うのでApproveします

@kantacky
Copy link
Copy Markdown
Member Author

Copilotの指摘直してもいいと思うけど、ほぼ問題ないと思うのでApproveします

ごめんなさい、いま慌てて直してました

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/repository/notification_dispatch.go
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/service/notification_dispatch.go
UNNEST + JOIN 化した実装を取りやめ、通知IDごとに
UPDATE notification_target_users ... WHERE notification_id = ? AND user_id IN ?
を発行する素直な実装に差し戻した。RowsAffected を見て
更新が発生した通知IDのみ後続の取得対象に含める挙動は維持する。
OpenAPI 上 /v1/notifications/dispatch は「送信状態に関わらずまとめて送信する」
仕様であり、再ディスパッチ時にも notified_at を最新の送信時刻で更新する必要がある。
そのため UPDATE 条件から notified_at IS NULL を外し、対象ユーザーの行を
無条件に now で更新するようにした。
OpenAPI の /v1/notifications/dispatch は送信状態に関わらず指定 ID の通知を
まとめて再送する仕様であるため、サービス層で NotifiedAt != nil の TargetUser を
スキップしている分岐を取り除き、全ターゲットユーザーを FCM 送信対象にする。
notified_at の更新はリポジトリ側で全ユーザーを上書きする実装に揃える。
DispatchNotifications をユニットテストで検証できるようにするため、
*messaging.Client への直接依存を MessagingClient interface
(SendEachForMulticast のみ) に差し替える。
*messaging.Client は引き続きこの interface を満たすため呼び出し側に変更はない。
通知ID指定からの送信フロー全体をスタブで検証する。
- 対象通知が存在しない / TargetUsers が空のときは FCM もリポジトリも呼ばない
- FCM トークン未登録ユーザーや既通知ユーザーも deliveries に含めて再送扱いにする
- FCM 部分成功時は成功ユーザーのみ delivered として記録する
- バッチ全体エラー時は dispatch を呼ばずエラーを握り潰してログのみ出す
- リポジトリ/FCMトークン取得のエラーはそのまま伝搬する
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/service/notification_dispatch.go
Comment thread internal/service/notification_dispatch_test.go
Comment thread internal/service/notification_dispatch_test.go
@kantacky kantacky merged commit 3937815 into main Apr 28, 2026
8 checks passed
@kantacky kantacky deleted the update-db-schema branch April 28, 2026 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants