@@ -30,6 +30,19 @@ upcoming_events テーブル event_histories テーブル
30
30
31
31
## 🔄 データフロー
32
32
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
+
33
46
### イベントのライフサイクル
34
47
35
48
``` ruby
@@ -112,42 +125,108 @@ rake statistics:aggregation # 週1回で十分
112
125
113
126
## 🛠️ 実装詳細
114
127
115
- ### UpcomingEvents の更新処理
128
+ ### UpcomingEvents の更新処理(実際のコード)
116
129
117
130
``` ruby
118
131
# lib/upcoming_events/aggregation.rb
119
132
class 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
+
120
141
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 # 新しいイベントを取得
131
146
end
132
147
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) }
133
161
end
134
162
```
135
163
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 の集計処理(実際のコード)
137
179
138
180
``` ruby
139
181
# lib/statistics/aggregation.rb
140
182
class 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
141
211
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
151
230
end
152
231
end
153
232
end
0 commit comments