@@ -30,6 +30,19 @@ upcoming_events テーブル event_histories テーブル
3030
3131## 🔄 データフロー
3232
33+ ### データ収集範囲とタイミング
34+
35+ ``` ruby
36+ # UpcomingEvents: 1ヶ月前 〜 2ヶ月後
37+ # 例:1月8日実行時
38+ UpcomingEvents 収集範囲: 2024 / 12 / 09 〜 2025 / 03 / 08
39+ 削除対象: 2024 / 12 / 08 以前に終了したイベント
40+
41+ # EventHistory: 指定期間(通常は前週)
42+ # 例:月曜日実行時
43+ EventHistory 収集範囲: 前週の月曜 〜 日曜(7 日間)
44+ ```
45+
3346### イベントのライフサイクル
3447
3548``` ruby
@@ -112,42 +125,108 @@ rake statistics:aggregation # 週1回で十分
112125
113126## 🛠️ 実装詳細
114127
115- ### UpcomingEvents の更新処理
128+ ### UpcomingEvents の更新処理(実際のコード)
116129
117130``` ruby
118131# lib/upcoming_events/aggregation.rb
119132class UpcomingEvents ::Aggregation
133+ def initialize (args )
134+ # NOTE: 1ヶ月前 〜 2ヶ月後のイベント情報を対象に収集
135+ today = Time .zone.today
136+ @from = today - 1 .months + 1 .day # 1ヶ月前から
137+ @to = today + 2 .months # 2ヶ月後まで
138+ @provider = args[:provider ]
139+ end
140+
120141 def run
121- # 1. 古いデータを削除
122- UpcomingEvent .delete_all
123-
124- # 2. 各プロバイダから未来のイベントを取得
125- fetch_from_connpass
126- fetch_from_doorkeeper
127-
128- # 3. DBに保存(過去のイベントは除外)
129- events.select { |e | e[:date ] > Date .today }.each do |event |
130- UpcomingEvent .create!(event)
142+ puts " UpcomingEvents aggregate"
143+ with_notifying do
144+ delete_upcoming_events # 古いイベントを削除
145+ execute # 新しいイベントを取得
131146 end
132147 end
148+
149+ private
150+
151+ def delete_upcoming_events
152+ # 1ヶ月より前に終了したイベントを削除
153+ UpcomingEvent .until(@from ).delete_all
154+ end
155+ end
156+
157+ # app/models/upcoming_event.rb
158+ class UpcomingEvent < ApplicationRecord
159+ # untilスコープ: 指定日より前に終了したイベント
160+ scope :until , -> (date) { where(' event_end_at < ?' , date.beginning_of_day) }
133161end
134162```
135163
136- ### EventHistory の集計処理
164+ #### 削除メカニズムの詳細
165+
166+ 1 . ** 1ヶ月分のバッファー期間**
167+ - 即座に削除せず、1ヶ月前まで保持
168+ - 例:1月8日実行時、12月8日より前のイベントを削除
169+
170+ 2 . ** event_end_at ベースの判定**
171+ - イベント終了時刻を基準に削除判定
172+ - 開始時刻ではない点が重要
173+
174+ 3 . ** delete_all による一括削除**
175+ - コールバックを実行しない高速削除
176+ - トランザクション内で安全に実行
177+
178+ ### EventHistory の集計処理(実際のコード)
137179
138180``` ruby
139181# lib/statistics/aggregation.rb
140182class Statistics ::Aggregation
183+ def initialize (args )
184+ @from , @to = aggregation_period(args[:from ], args[:to ])
185+ @provider = args[:provider ]
186+ @dojo_id = args[:dojo_id ].to_i if args[:dojo_id ].present?
187+ end
188+
189+ def run
190+ puts " Aggregate for #{ @from } ~#{ @to } "
191+ with_notifying do
192+ delete_event_histories # 期間内の既存データを削除
193+ execute # 新しいデータを取得・保存
194+ end
195+ end
196+
197+ private
198+
199+ def delete_event_histories
200+ target_period = @from .beginning_of_day..@to .end_of_day
201+ # 各プロバイダごとに削除処理
202+ (@externals .keys + @internals .keys).each do |kind |
203+ " Statistics::Tasks::#{ kind.to_s.camelize } " .constantize
204+ .delete_event_histories(target_period, @dojo_id )
205+ end
206+ end
207+ end
208+
209+ # lib/statistics/tasks/doorkeeper.rb
210+ class Statistics ::Tasks ::Doorkeeper
141211 def run
142- # 指定期間の過去イベントのみを集計
143- period = @from ..@to # 過去の期間
144-
145- # 各プロバイダから過去のイベントを取得
146- fetch_past_events(period)
147-
148- # EventHistoryに保存(実際に開催されたもののみ)
149- events.each do |event |
150- EventHistory .create!(event) if event[:status ] == ' held'
212+ @dojos .each do |dojo |
213+ dojo.dojo_event_services.for(:doorkeeper ).each do |service |
214+ events = @client .fetch_events(group_id: service.group_id)
215+
216+ events.each do |e |
217+ # 実際に開催されたイベントのみ保存
218+ next unless e[:group ].to_s == service.group_id
219+
220+ EventHistory .create!(
221+ dojo_id: dojo.id,
222+ dojo_name: dojo.name,
223+ event_id: e[:id ],
224+ event_url: e[:public_url ],
225+ participants: e[:participants ], # 実際の参加者数
226+ evented_at: Time .zone.parse(e[:starts_at ])
227+ )
228+ end
229+ end
151230 end
152231 end
153232end
0 commit comments