Skip to content

Commit a5745bd

Browse files
committed
Doorkeeper API の504エラーに対するリトライ処理とタイムアウト設定を追加
## 変更内容 ### 1. タイムアウト設定の追加 (lib/event_service/client.rb) - 接続タイムアウト: 10秒 - 読み取りタイムアウト: 60秒 - 無限待機を防止 ### 2. サーバーエラーのリトライ処理 (lib/event_service/providers/doorkeeper.rb) - 502/503/504エラーを検出して自動リトライ - Exponential backoff: 10秒 → 20秒 → 40秒 - 最大3回までリトライ - group_id を含む詳細なエラーログ ### 3. 詳細なログ出力 (lib/statistics/tasks/doorkeeper.rb) - どのDojoを処理中かを表示 - 取得成功時のイベント数を表示 - エラー発生時にDojo名とgroup_idを記録 ## 動作確認 ローカル環境で以下のタスクを実行し、正常動作を確認: - `bundle exec rails statistics:aggregation` - 51個のDojoを正常に処理 - `bundle exec rails upcoming_events:aggregation` - Connpass: 116イベント取得 - Doorkeeper: 2箇所で504エラー発生 → リトライで成功 ## テスト 全216テストが成功: ``` bundle exec rspec spec 216 examples, 0 failures ``` ## 関連Issue 統計/地図スクリプトの504エラーに対応
1 parent b42a31c commit a5745bd

File tree

3 files changed

+38
-20
lines changed

3 files changed

+38
-20
lines changed

lib/event_service/client.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def get(path, params)
1414
private
1515

1616
def connection_for(endpoint, proxy)
17-
Faraday.new(endpoint, proxy: proxy) do |f|
17+
Faraday.new(endpoint, proxy: proxy, request: { open_timeout: 10, timeout: 60 }) do |f|
1818
f.response :logger if self.class.debug
1919

2020
# faraday標準のJSONパーサーを使用

lib/event_service/providers/doorkeeper.rb

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,48 @@ def search(keyword:)
1717
end
1818

1919
# NOTE: since_at, until_at は DateTime で指定
20-
def fetch_events(group_id:, since_at: @default_since, until_at: @default_until)
21-
begin
22-
params = {
23-
page: 1,
24-
since: since_at.utc.iso8601,
25-
until: until_at.utc.iso8601
26-
}
27-
events = []
20+
def fetch_events(group_id:, since_at: @default_since, until_at: @default_until, retry_count: 0)
21+
params = {
22+
page: 1,
23+
since: since_at.utc.iso8601,
24+
until: until_at.utc.iso8601
25+
}
26+
events = []
2827

29-
loop do
30-
part = @client.get("groups/#{group_id}/events", params)
28+
loop do
29+
part = @client.get("groups/#{group_id}/events", params)
3130

32-
break if part.size.zero?
31+
break if part.size.zero?
3332

34-
events.push(*part.map { |e| e[:event] })
33+
events.push(*part.map { |e| e[:event] })
3534

36-
break if part.size < 25 # 25 items / 1 request
35+
break if part.size < 25 # 25 items / 1 request
3736

38-
params[:page] += 1
39-
end
40-
41-
events
42-
rescue Faraday::ClientError => e
43-
raise e unless e.response[:status] == 429
37+
params[:page] += 1
38+
end
4439

40+
events
41+
rescue Faraday::ClientError => e
42+
# 429: Rate Limit
43+
if e.response[:status] == 429
4544
puts 'API rate limit exceeded.'
4645
puts "This task will retry in 60 seconds from now(#{Time.zone.now})."
4746
sleep 60
4847
retry
48+
else
49+
raise e
50+
end
51+
rescue Faraday::ServerError => e
52+
# 502, 503, 504: Server errors
53+
if [502, 503, 504].include?(e.response[:status]) && retry_count < 3
54+
wait_time = 2 ** retry_count * 10 # Exponential backoff: 10, 20, 40 seconds
55+
puts "Server error (#{e.response[:status]}) for group_id: #{group_id}."
56+
puts "Retrying in #{wait_time} seconds... (attempt #{retry_count + 1}/3)"
57+
sleep wait_time
58+
fetch_events(group_id: group_id, since_at: since_at, until_at: until_at, retry_count: retry_count + 1)
59+
else
60+
puts "Failed to fetch events for group_id: #{group_id} after #{retry_count} retries."
61+
raise e
4962
end
5063
end
5164
end

lib/statistics/tasks/doorkeeper.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def initialize(dojos, period)
1818
def run
1919
@dojos.each do |dojo|
2020
dojo.dojo_event_services.for(:doorkeeper).each do |dojo_event_service|
21+
puts " Fetching events for #{dojo.name} (group_id: #{dojo_event_service.group_id})"
2122
events = @client.fetch_events(**@params.merge(group_id: dojo_event_service.group_id))
2223
(events || []).compact.each do |e|
2324
next unless e[:group].to_s == dojo_event_service.group_id
@@ -31,6 +32,10 @@ def run
3132
participants: e[:participants],
3233
evented_at: Time.zone.parse(e[:starts_at]))
3334
end
35+
puts " ✓ Successfully fetched #{events&.size || 0} events"
36+
rescue => e
37+
puts " ✗ Failed to fetch events for #{dojo.name} (group_id: #{dojo_event_service.group_id}): #{e.message}"
38+
raise e
3439
end
3540
end
3641
end

0 commit comments

Comments
 (0)