Open4
バッチ・メール

目次
- バッチの設計
- 検証コード
- DBの理解

バッチの設計
システムの停止
-
主な停止理由
- awsなどの基盤の障害
- panicの発生
- oom
- プロセスの矯正終了
- その他メトリクス
- cpuが100%以上の場合は遅延
- ネットワーク
- 遅延 or タイムアウト
気を付けること要点
- 停止しない
- メモリ OOM
- 実行時間
- 実行時間が長いとデータをロックする時間も長いのでいつ実行するか?は大事
- ロック
- リトライ必要じゃない?
気をつけること
- 安定性と堅牢性
- エラーハンドリング
- 外部サービスの一時的な接続エラー
- リトライ、スキップ
- 外部サービスの一時的な接続エラー
- 冪等性
- 同じバッチが複数回実行されても最終的なシステムの状態が一貫している
- ex) 同じ日付なら同じ結果になるとか
- 最初の抽出データが日付で区切られていることが多いので
- ex) 同じ日付なら同じ結果になるとか
- 同じバッチが複数回実行されても最終的なシステムの状態が一貫している
- リトライ戦略
- 外部サービス連携(例: SendGrid API)で一時的なエラーが発生した場合に、どのようにリトライするかの戦略
- 回数、間隔、指数バックオフなど
- 外部サービス連携(例: SendGrid API)で一時的なエラーが発生した場合に、どのようにリトライするかの戦略
- データ整合性の維持
- システム障害の時などはトランザクションなどでロールバック
- エラーハンドリング
- パフォーマンス
- 実行時間の見積もり
- リソース消費の最適化
- 処理単位とバッチサイズ
- 一気にやるのではなく、適切なサイズに分けること
- メモリ使用量の削減
- エラー時
- 一気にやるのではなく、適切なサイズに分けること
- 運用と監視
- ログの出力
- 開始、進捗、完了をログ出力が基本
- 進捗は「件数」が基本
- エラーログ
- ユーザidなどのデータを特定できる情報が必要
- 開始、進捗、完了をログ出力が基本
- 監視とアラート
- 通知機能
- ログの出力
- セキュリティ
- 認証管理
- DBアクセス・APIキー
- 認証管理

検証コード
実装参考
参考2 jordan-wright/email
- 簡易メール送信
参考 3
go html
送信サンプル
<h1>{{.Title}}</h1>
<p>{{.Message}}</p>
package main
import (
"bytes"
"embed"
"fmt"
"html/template"
"log"
"github.com/yosssi/gohtml"
)
type EmailData struct {
Title string
Message string
}
//go:embed email_template.html
var emailTemplateFS embed.FS
func main() {
// 1. 埋め込みファイル読み込み
tmplContent, err := emailTemplateFS.ReadFile("email_template.html")
if err != nil {
log.Fatal("テンプレート読み込み失敗:", err)
}
// 2. テンプレート作成
tmpl := template.Must(template.New("email").Parse(string(tmplContent)))
// 3. データ適用
var buf bytes.Buffer
err = tmpl.Execute(&buf, EmailData{
Title: "こんにちは",
Message: "GoでHTMLメールを送っています!",
})
if err != nil {
log.Fatal("テンプレート実行失敗:", err)
}
// 4. 整形表示(開発中の確認などに)
formatted := gohtml.Format(buf.String())
fmt.Println(formatted)
// 5. メール送信時は buf.Bytes() を使えばOK
// email.HTML = buf.Bytes()
}

DBの理解
ロック
- データロック
- デットロック
- バッチでロックしているデータにAPIでもロックをかけて処理が走る
- user user_settingがあったとして、バッチでuserにロックを apiでuser_settingにロックをかける
- デットロックが発生した場合
- 片方を失敗させて処理を継続させる
- バッチでロックしているデータにAPIでもロックをかけて処理が走る
- ロックの粒度
- ロックモード
- 共有
- selectはできる
- 排他ロック
- selectもできない
- 共有
- デットロック
デットロックはなぜ発生するか?
- dbにはコネクションを複数貼ることができる
- batchの実行毎、APIの1リクエスト事
- コネクション毎に独立しているので、別のコネクションのトランザクションの情報などは知らない為発生する
データのパッチ当て
-
SET SESSION lock_wait_timeout=5;
などを指定するのは、優先的にパッチ側を失敗させる。- これは、「オンラインサービス(API、Webサイトなど)の可用性維持が最優先」だから
- トランザクションを張るべきである