同期成功
コマンドシグネチャ
php artisan analyzerdb:sync-crawl-success-from-analyzer --data-type=SummaryProduct [--limit=100]
php artisan analyzerdb:sync-crawl-success-from-analyzer --data-type=SummaryProductReview [--limit=100]
php artisan analyzerdb:sync-crawl-success-from-analyzer --data-type=SummaryCategory [--limit=100]
php artisan analyzerdb:sync-crawl-success-from-analyzer --data-type=SummarySearchQuery [--limit=100]
目的
これらのコマンドは、コンソールデータベース(gb_console)のサマリーウィッシュリストテーブルのレコードが、アナライザーデータベース(gb_analyzer)で正常に処理されたかどうかを検証します。適切なタイムスタンプでアナライザーデータベースに一致するレコードが見つかった場合、コンソールデータベースの対応するレコードは「成功」クロールステータスで更新され、両方のデータベース間でデータ処理パイプラインの正確な追跡を維持します。
シーケンス図
メインコマンドフロー
sequenceDiagram
participant System
participant Command as analyzerdb:sync-crawl-success-from-analyzer
participant Repository as SummaryWishlist*Repository
participant ConsoleDB[(gb_console)]
participant Logger
participant Slack
Note over System,Slack: コマンド実行フロー(5分毎)
rect rgb(200, 255, 200)
Note right of System: 正常ケース - コマンド処理
System->>Command: --data-typeパラメータで実行
Command->>Logger: パラメータ付きでコマンド開始をログ
Command->>Repository: chunkDataUpdateCrawlStatusSuccess()
Repository->>ConsoleDB: crawl_status = Crawlingのレコードをクエリ
ConsoleDB-->>Repository: 検証が必要なレコードを返す
Repository-->>Command: レコードのチャンクを返す(最大:limitオプション)
rect rgb(200, 230, 255)
loop レコードの各チャンクに対して
Note right of Command: バッチジョブディスパッチ
Command->>Command: データタイプに基づく専用ジョブをディスパッチ
Command->>Logger: チャンク処理開始をログ
end
end
Command->>Logger: コマンド完了をログ
Command->>Slack: 処理サマリー通知を送信
end
rect rgb(255, 200, 200)
Note right of System: エラーハンドリング
rect rgb(255, 230, 230)
alt コマンドエラーが発生
Command->>Logger: コマンドエラー詳細をログ
Command->>Slack: エラー通知を送信
end
end
end
SummaryProductジョブフロー
sequenceDiagram
participant Job as SummaryProductJob
participant ProductRepo as ProductRepositoryInterface
participant AnalyzerDB[(gb_analyzer.products)]
participant ConsoleRepo as SummaryWishlistProductRepository
participant ConsoleDB[(gb_console.summary_wishlist_products)]
participant Logger
participant Slack
Note over Job,Slack: 商品検証ジョブフロー
rect rgb(200, 255, 200)
Note right of Job: 正常ケース - 商品検証
Job->>Logger: レコード数でジョブ開始をログ
Job->>Job: レコードからmall_id、input_type、inputを抽出
Job->>ProductRepo: ルックアップキーで商品をクエリ
ProductRepo->>AnalyzerDB: mall_id、input_type、inputが一致するSELECT
Note right of AnalyzerDB: 時間制約:crawl_created_at >= updated_at
AnalyzerDB-->>ProductRepo: 一致する商品を返す
ProductRepo-->>Job: 検証済み商品レコードを返す
rect rgb(255, 255, 200)
alt アナライザーDBで商品が見つかった
Note right of Job: 成功更新
Job->>ConsoleRepo: updateByConditions(crawl_status = Success)
ConsoleRepo->>ConsoleDB: UPDATE crawl_status = 2 WHERE id IN (...)
ConsoleDB-->>ConsoleRepo: バッチ更新を確認
ConsoleRepo-->>Job: 更新数を返す
rect rgb(230, 200, 255)
Note right of Job: 成功監視
Job->>Logger: 数付きで成功更新をログ
Job->>Slack: 統計付きで成功通知を送信
end
else 一致する商品なし
Note right of Job: アクション不要
Job->>Logger: 更新不要をログ
end
end
end
rect rgb(255, 200, 200)
Note right of Job: エラーハンドリング
rect rgb(255, 230, 230)
alt データベースエラーが発生
Job->>Job: デッドロック/接続エラーを検出
Job->>Job: 指数バックオフリトライを実装
Job->>Logger: スリープ時間付きでリトライ試行をログ
rect rgb(233, 196, 196)
alt 最大リトライ回数超過(5回)
Job->>Logger: スタックトレース付きで最終エラーをログ
Job->>Slack: エラー通知を送信
end
end
end
end
end
SummaryProductReviewジョブフロー
sequenceDiagram
participant Job as SummaryProductReviewJob
participant ReviewRepo as ReviewRepositoryInterface
participant AnalyzerDB[(gb_analyzer.reviews)]
participant ConsoleRepo as SummaryWishlistProductReviewRepository
participant ConsoleDB[(gb_console.summary_wishlist_product_reviews)]
participant Logger
participant Slack
Note over Job,Slack: 商品レビュー検証ジョブフロー
rect rgb(200, 255, 200)
Note right of Job: 正常ケース - レビュー検証
Job->>Logger: レコード数でジョブ開始をログ
Job->>Job: 関連商品から商品識別子を抽出
Job->>ReviewRepo: 商品識別子でレビューをクエリ
ReviewRepo->>AnalyzerDB: mall_id、商品識別子が一致するSELECT
Note right of AnalyzerDB: 時間制約:crawl_created_at >= updated_at
AnalyzerDB-->>ReviewRepo: 一致するレビューを返す
ReviewRepo-->>Job: 検証済みレビューレコードを返す
rect rgb(255, 255, 200)
alt アナライザーDBでレビューが見つかった
Note right of Job: 成功更新
Job->>ConsoleRepo: updateBySummaryWishlistProductIds()
ConsoleRepo->>ConsoleDB: UPDATE crawl_status = 2 WHERE product_id IN (...)
ConsoleDB-->>ConsoleRepo: バッチ更新を確認
ConsoleRepo-->>Job: 更新数を返す
rect rgb(230, 200, 255)
Note right of Job: 成功監視
Job->>Logger: 数付きで成功更新をログ
Job->>Slack: 統計付きで成功通知を送信
end
else 一致するレビューなし
Note right of Job: アクション不要
Job->>Logger: 更新不要をログ
end
end
end
rect rgb(255, 200, 200)
Note right of Job: エラーハンドリング
rect rgb(255, 230, 230)
alt データベースエラーが発生
Job->>Job: デッドロック/接続エラーを検出
Job->>Job: 指数バックオフリトライを実装
Job->>Logger: スリープ時間付きでリトライ試行をログ
rect rgb(233, 196, 196)
alt 最大リトライ回数超過(5回)
Job->>Logger: スタックトレース付きで最終エラーをログ
Job->>Slack: エラー通知を送信
end
end
end
end
end
SummaryCategoryジョブフロー
sequenceDiagram
participant Job as SummaryCategoryJob
participant CategoryRepo as TempCategoryRankingRepositoryInterface
participant AnalyzerDB[(gb_analyzer.t_category_rankings)]
participant ConsoleRepo as SummaryWishlistCategoryRepository
participant ConsoleDB[(gb_console.summary_wishlist_categories)]
participant Logger
participant Slack
Note over Job,Slack: カテゴリ検証ジョブフロー
rect rgb(200, 255, 200)
Note right of Job: 正常ケース - カテゴリ検証
Job->>Logger: レコード数でジョブ開始をログ
Job->>Job: レコードからmall_id、category_idを抽出
Job->>CategoryRepo: ルックアップキーでカテゴリランキングをクエリ
CategoryRepo->>AnalyzerDB: mall_id、category_idが一致するSELECT
Note right of AnalyzerDB: 時間制約:crawl_created_at >= updated_at
AnalyzerDB-->>CategoryRepo: 一致するカテゴリランキングを返す
CategoryRepo-->>Job: 検証済みカテゴリレコードを返す
rect rgb(255, 255, 200)
alt アナライザーDBでカテゴリが見つかった
Note right of Job: 成功更新
Job->>ConsoleRepo: updateByConditions(crawl_status = Success)
ConsoleRepo->>ConsoleDB: UPDATE crawl_status = 2 WHERE id IN (...)
ConsoleDB-->>ConsoleRepo: バッチ更新を確認
ConsoleRepo-->>Job: 更新数を返す
rect rgb(230, 200, 255)
Note right of Job: 成功監視
Job->>Logger: 数付きで成功更新をログ
Job->>Slack: 統計付きで成功通知を送信
end
else 一致するカテゴリなし
Note right of Job: アクション不要
Job->>Logger: 更新不要をログ
end
end
end
rect rgb(255, 200, 200)
Note right of Job: エラーハンドリング
rect rgb(255, 230, 230)
alt データベースエラーが発生
Job->>Job: デッドロック/接続エラーを検出
Job->>Job: 指数バックオフリトライを実装
Job->>Logger: スリープ時間付きでリトライ試行をログ
rect rgb(233, 196, 196)
alt 最大リトライ回数超過(5回)
Job->>Logger: スタックトレース付きで最終エラーをログ
Job->>Slack: エラー通知を送信
end
end
end
end
end
SummarySearchQueryジョブフロー
sequenceDiagram
participant Job as SummarySearchQueryJob
participant SearchRepo as TempSearchQueryRankingRepositoryInterface
participant AnalyzerDB[(gb_analyzer.t_sq_rankings)]
participant ConsoleRepo as SummaryWishlistSearchQueryRepository
participant ConsoleDB[(gb_console.summary_wishlist_search_queries)]
participant Logger
participant Slack
Note over Job,Slack: 検索クエリ検証ジョブフロー
rect rgb(200, 255, 200)
Note right of Job: 正常ケース - 検索クエリ検証
Job->>Logger: レコード数でジョブ開始をログ
Job->>Job: レコードからmall_id、keywordを抽出
Job->>SearchRepo: ルックアップキーで検索クエリランキングをクエリ
SearchRepo->>AnalyzerDB: mall_id、keywordが一致するSELECT
Note right of AnalyzerDB: 時間制約:crawl_created_at >= updated_at
AnalyzerDB-->>SearchRepo: 一致する検索クエリランキングを返す
SearchRepo-->>Job: 検証済み検索クエリレコードを返す
rect rgb(255, 255, 200)
alt アナライザーDBで検索クエリが見つかった
Note right of Job: 成功更新
Job->>ConsoleRepo: updateByConditions(crawl_status = Success)
ConsoleRepo->>ConsoleDB: UPDATE crawl_status = 2 WHERE id IN (...)
ConsoleDB-->>ConsoleRepo: バッチ更新を確認
ConsoleRepo-->>Job: 更新数を返す
rect rgb(230, 200, 255)
Note right of Job: 成功監視
Job->>Logger: 数付きで成功更新をログ
Job->>Slack: 統計付きで成功通知を送信
end
else 一致する検索クエリなし
Note right of Job: アクション不要
Job->>Logger: 更新不要をログ
end
end
end
rect rgb(255, 200, 200)
Note right of Job: エラーハンドリング
rect rgb(255, 230, 230)
alt データベースエラーが発生
Job->>Job: デッドロック/接続エラーを検出
Job->>Job: 指数バックオフリトライを実装
Job->>Logger: スリープ時間付きでリトライ試行をログ
rect rgb(233, 196, 196)
alt 最大リトライ回数超過(5回)
Job->>Logger: スタックトレース付きで最終エラーをログ
Job->>Slack: エラー通知を送信
end
end
end
end
end
データベーススキーマ
コンソールデータベーステーブル(gb_console)
erDiagram
summary_wishlist_products {
bigint id PK
string input "商品の入力"
string input_type "入力のタイプ:jan、asin、rakuten_id"
bigint mall_id FK "mallsテーブルへの外部キー"
integer crawl_status "クロールのステータス(SummaryProductJobによって更新)"
timestamp updated_at "時間制約検証に使用"
}
summary_wishlist_product_reviews {
bigint id PK
bigint summary_wishlist_product_id FK "summary_wishlist_productsへの外部キー"
integer crawl_status "クロールのステータス(SummaryProductReviewJobによって更新)"
timestamp updated_at "時間制約検証に使用"
}
summary_wishlist_categories {
bigint id PK
string category_id "カテゴリ識別子"
bigint mall_id FK "mallsテーブルへの外部キー"
integer crawl_status "クロールのステータス(SummaryCategoryJobによって更新)"
timestamp updated_at "時間制約検証に使用"
}
summary_wishlist_search_queries {
bigint id PK
bigint mall_id FK "mallsテーブルへの外部キー"
string keyword "検索キーワード"
integer crawl_status "クロールのステータス(SummarySearchQueryJobによって更新)"
timestamp updated_at "時間制約検証に使用"
}
summary_wishlist_products ||--o| summary_wishlist_product_reviews : "has one"
アナライザーデータベーステーブル(gb_analyzer)
erDiagram
products {
bigint id PK
bigint mall_id FK "モール識別子(ルックアップに使用)"
string mall_product_id "モールからの商品ID"
string jan_code "JANコード(null可、ルックアップに使用)"
string input_type "入力タイプ:asin、jan、rakuten_id(ルックアップに使用)"
timestamp crawl_created_at "商品がクロールされた時刻(時間制約フィールド)"
}
reviews {
bigint id PK
bigint mall_id FK "モール識別子(ルックアップに使用)"
string mall_product_id "モールからの商品ID(ルックアップに使用)"
string jan_code "JANコード(null可、最大50文字、ルックアップに使用)"
timestamp crawl_created_at "レビューがクロールされた時刻(時間制約フィールド)"
}
t_category_rankings {
bigint id PK
bigint mall_id FK "モール識別子(ルックアップに使用)"
string category_id "カテゴリ識別子(ルックアップに使用)"
timestamp crawl_created_at "ランキングがクロールされた時刻(時間制約フィールド)"
}
t_sq_rankings {
bigint id PK
string keyword "検索キーワード(ルックアップに使用、最大100文字)"
bigint mall_id FK "モール識別子(ルックアップに使用)"
timestamp crawl_created_at "ランキングがクロールされた時刻(時間制約フィールド)"
}
検証ルックアップキー
SummaryProduct検証
- コンソールテーブル:
summary_wishlist_products - アナライザーテーブル:
products - ルックアップキー:
mall_id(integer)- 完全一致必須input_type(string)- jan、asin、またはrakuten_idinput(string)- 実際の商品識別子
- 時間制約:
products.crawl_created_at >= summary_wishlist_products.updated_at - 更新フィールド:
crawl_status = 2(成功)
SummaryProductReview検証
- コンソールテーブル:
summary_wishlist_product_reviews - アナライザーテーブル:
reviews - ルックアップキー:
mall_id(integer)- 関連summary_wishlist_productから- 商品識別子 - 関連商品のinput_typeに基づく
- 時間制約:
reviews.crawl_created_at >= summary_wishlist_product_reviews.updated_at - 更新フィールド:
crawl_status = 2(成功)
SummaryCategory検証
- コンソールテーブル:
summary_wishlist_categories - アナライザーテーブル:
t_category_rankings - ルックアップキー:
mall_id(integer)- 完全一致必須category_id(string)- 完全一致必須
- 時間制約:
t_category_rankings.crawl_created_at >= summary_wishlist_categories.updated_at - 更新フィールド:
crawl_status = 2(成功)
SummarySearchQuery検証
- コンソールテーブル:
summary_wishlist_search_queries - アナライザーテーブル:
t_sq_rankings - ルックアップキー:
mall_id(integer)- 完全一致必須keyword(string)- 完全一致必須
- 時間制約:
t_sq_rankings.crawl_created_at >= summary_wishlist_search_queries.updated_at - 更新フィールド:
crawl_status = 2(成功)
CrawlStatus列挙値
すべてのコンソールテーブルのcrawl_statusフィールドは以下の列挙値を使用します:
- 0(NotCrawled): 新しいレコードの初期状態
- 1(Crawling): レコードは現在クローラーによって処理中(同期コマンドによってフィルタリング)
- 2(Success): 処理が正常に完了(これらのコマンドによって更新)
- 3(Failed): 処理がエラーで失敗
- 4(Error): 処理中にシステムエラーが発生
使用されるリポジトリインターフェース
- SummaryWishlistProductRepositoryInterface:
summary_wishlist_products操作を処理 - SummaryWishlistProductReviewRepositoryInterface:
summary_wishlist_product_reviews操作を処理 - SummaryWishlistCategoryRepositoryInterface:
summary_wishlist_categories操作を処理 - SummaryWishlistSearchQueryRepositoryInterface:
summary_wishlist_search_queries操作を処理 - ProductRepositoryInterface: アナライザーデータベースの
productsテーブルをクエリ - ReviewRepositoryInterface: アナライザーデータベースの
reviewsテーブルをクエリ - TempCategoryRankingRepositoryInterface: アナライザーデータベースの
t_category_rankingsテーブルをクエリ - TempSearchQueryRankingRepositoryInterface: アナライザーデータベースの
t_sq_rankingsテーブルをクエリ
詳細
パラメータ
--data-type: 検証するデータのタイプを指定する必須パラメータSummaryProduct:summary_wishlist_productsテーブルの商品データを検証SummaryProductReview:summary_wishlist_product_reviewsテーブルの商品レビューデータを検証SummaryCategory:summary_wishlist_categoriesテーブルのカテゴリデータを検証SummarySearchQuery:summary_wishlist_search_queriesテーブルの検索クエリデータを検証
--limit=N: 処理のバッチサイズを制御するオプションパラメータ(デフォルト:チャンクあたり100レコード)
頻度
各データタイプ(SummaryProduct、SummaryProductReview、SummaryCategory、SummarySearchQuery)に対して5分毎
依存関係
- コンソールデータベース(
gb_console):crawl_status = Crawlingのサマリーウィッシュリストテーブルにレコードが含まれている必要があります - アナライザーデータベース(
gb_analyzer): 対応するテーブルに処理済みデータが含まれている必要があります:- SummaryProduct検証用の
productsテーブル - SummaryProductReview検証用の
reviewsテーブル - SummaryCategory検証用の
t_category_rankingsテーブル - SummarySearchQuery検証用の
t_sq_rankingsテーブル
- SummaryProduct検証用の
- Laravelキューシステム: 非同期ジョブ処理用
- リポジトリインターフェース: データベース抽象化とバッチ操作用
出力
テーブル
-
summary_wishlist_products:
crawl_statusフィールドを2(成功)に更新- 更新者:
SummaryProductJob - ルックアップ方法:
mall_id、input_type、inputフィールドに基づく - 時間制約:
crawl_created_at >= updated_at
- 更新者:
-
summary_wishlist_product_reviews:
crawl_statusフィールドを2(成功)に更新- 更新者:
SummaryProductReviewJob - ルックアップ方法: 関連商品識別子に基づく
- 時間制約:
crawl_created_at >= updated_at
- 更新者:
-
summary_wishlist_categories:
crawl_statusフィールドを2(成功)に更新- 更新者:
SummaryCategoryJob - ルックアップ方法:
mall_idとcategory_idフィールドに基づく - 時間制約:
crawl_created_at >= updated_at
- 更新者:
-
summary_wishlist_search_queries:
crawl_statusフィールドを2(成功)に更新- 更新者:
SummarySearchQueryJob - ルックアップ方法:
mall_idとkeywordフィールドに基づく - 時間制約:
crawl_created_at >= updated_at
- 更新者:
サービス
- ジョブキュー: 各データタイプの専用検証ジョブをディスパッチ
- データベーストランザクション: ロールバック機能付きのアトミック更新を保証
- Slack通知: 処理統計付きの成功/エラー通知を送信
- ログシステム: タイムスタンプとレコード数付きの詳細実行ログを記録
エラーハンドリング
ログ
システムは監視とデバッグのための包括的なログを生成します:
- コマンド実行ログ: データタイプとlimitパラメータ付きの開始/終了タイムスタンプ
- 進捗追跡: 処理されたチャンク数と検証された総レコード数
- 成功更新: 特定のIDで成功ステータスに更新されたレコード数
- エラー詳細: ファイル/行情報とリトライ試行付きのデータベースエラー
- 時間制約違反: タイムスタンプ要件を満たさないレコード
Slack
設定されたSlackチャンネルに自動通知が送信されます:
- 成功通知: 処理統計(処理レコード数、更新数、実行時間)を含む
- エラー通知: コンテキストとスタックトレース付きの詳細エラーメッセージを含む
- リトライ通知: データベースエラーがリトライメカニズムをトリガーした時にアラート
- 最終失敗アラート: 最大リトライ試行回数を超えた時に送信
トラブルシューティング
データ確認
-
コンソールデータベースレコードの検証:
SELECT COUNT(*) FROM summary_wishlist_products WHERE crawl_status = 1; -- クロール中ステータス SELECT COUNT(*) FROM summary_wishlist_products WHERE crawl_status = 2; -- 成功ステータス -
アナライザーデータベース人口の確認:
SELECT COUNT(*) FROM products WHERE crawl_created_at >= NOW() - INTERVAL 1 HOUR; SELECT COUNT(*) FROM reviews WHERE crawl_created_at >= NOW() - INTERVAL 1 HOUR; -
時間制約の検証:
SELECT id, updated_at FROM summary_wishlist_products WHERE crawl_status = 1 ORDER BY updated_at DESC LIMIT 10;
ログ確認
- Laravelアプリケーションログ: コマンド実行詳細について
storage/logs/laravel.logを確認 - ジョブキューログ:
php artisan queue:failedコマンドを使用して失敗したジョブを監視 - データベースクエリログ: 遅いまたは失敗するデータベース操作をデバッグするためにクエリログを有効化
- Slackメッセージ履歴: エラーパターンと成功率について通知チャンネルを確認
一般的な問題と解決策
-
データベースデッドロック:
- 症状: Slackでのリトライ通知
- 解決策: システムは指数バックオフで自動的にリトライ(最大5回試行)
- 予防:
--limitパラメータでバッチサイズを減らすことを検討
-
一致するレコードなし:
- 症状: クロール中ステータスのレコードがあるにもかかわらずステータス更新なし
- 解決策: アナライザーデータベースに適切なタイムスタンプの最新データが含まれていることを確認
- 確認: クローラーとアナライザーシステムが正常に機能していることを確認
-
時間制約の問題:
- 症状: アナライザーデータベースにデータがあるにもかかわらずレコードがクロール中ステータスのまま
- 解決策: コンソールの
updated_atとアナライザーのcrawl_created_at間のタイムスタンプ整合性を確認 - 修正: データベース間でシステムクロックが同期されていることを確認
-
高処理負荷:
- 症状: コマンドタイムアウトまたは実行の遅延
- 解決策:
--limit=50またはそれ以下を使用してバッチサイズを減らす - 監視: データベースパフォーマンスとキューワーカー容量を確認