API の処理に時間がかかりすぎる問題 (#442) (#449)

Reviewed-on: #449
Co-authored-by: miteruzo <miteruzo@naver.com>
このコミットはプルリクエスト #449 でマージされました。
このコミットが含まれているのは:
2026-11-07 19:01:20 +09:00
committed by みてるぞ
コミット 8d00a6545e
8個のファイルの変更、367行の追加、161行の削除
+25 -14
ファイルの表示
@@ -37,20 +37,10 @@ class PostsController < ApplicationController
offset = (page - 1) * limit
pt_max_sql =
HistoryAccess.visible(PostVersion.all)
.select('post_id, MAX(created_at) AS max_updated_at')
.group('post_id')
.to_sql
updated_at_all_sql =
'GREATEST(posts.updated_at,' +
'COALESCE(pt_max.max_updated_at, posts.updated_at))'
needs_history_join = order[0] == 'updated_at' || updated_between.any?(&:present?)
q =
filtered_posts(locale)
.joins("LEFT JOIN (#{ pt_max_sql }) pt_max ON pt_max.post_id = posts.id")
.reselect('posts.*', Arel.sql("#{ updated_at_all_sql } AS updated_at_all"))
.preload(:external_tags, :uploaded_user, :parents, :children,
post_tags: [:sections, { tag: [:deerjikists, :materials,
:tag_names, :tag_descriptions] }])
@@ -66,12 +56,25 @@ class PostsController < ApplicationController
end
q = q.where('posts.created_at >= ?', created_between[0]) if created_between[0]
q = q.where('posts.created_at <= ?', created_between[1]) if created_between[1]
count_scope = q
if needs_history_join
history_times = HistoryAccess.visible(PostVersion.all)
.select('post_id, MAX(created_at) AS latest_at').group(:post_id)
q = q.joins("LEFT JOIN (#{ history_times.to_sql }) history_times " +
'ON history_times.post_id = posts.id')
updated_at_all_sql = 'GREATEST(posts.updated_at, ' +
'COALESCE(history_times.latest_at, posts.updated_at))'
end
if updated_between[0]
q = q.where("#{ updated_at_all_sql } >= ?", updated_between[0])
end
if updated_between[1]
q = q.where("#{ updated_at_all_sql } <= ?", updated_between[1])
end
count_scope = q if updated_between.any?(&:present?)
if needs_history_join
q = q.select('posts.*', "#{ updated_at_all_sql } AS updated_at")
end
sort_sql =
case order[0]
@@ -88,12 +91,20 @@ class PostsController < ApplicationController
.limit(limit)
.offset(offset)
.to_a
latest_version_times =
if needs_history_join
{ }
else
HistoryAccess.visible(PostVersion.where(post_id: posts.map(&:id)))
.group(:post_id).maximum(:created_at)
end
q = q.except(:select, :order)
count_scope = count_scope.except(:select, :order)
render json: { posts: posts.map { |post|
updated_at = [post.updated_at, latest_version_times[post.id]].compact.max
PostRepr.base(post, language_code: locale.language_code)
.merge(updated_at: post.updated_at_all).tap do |json|
.merge('updated_at' => updated_at).tap do |json|
json['thumbnail'] =
if post.thumbnail.attached?
rails_storage_proxy_url(post.thumbnail, only_path: false)
@@ -101,7 +112,7 @@ class PostsController < ApplicationController
nil
end
end
}, count: q.group_values.present? ? q.count.size : q.count }
}, count: count_scope.group_values.present? ? count_scope.count.size : count_scope.count }
end
def random