DEV: Do one query per month when exporting chat messages (#22746)

We did some testing and saw that making one query per month is 
cheaper than querying all chat messages at ones. Note that even 
though the export job will be performing one query per month, 
the exported messages will be streamed into a single CSV file, so 
nothing changes from the user's point of view.
This commit is contained in:
Andrei Prigorshnev 2023-07-27 21:56:32 +04:00 committed by GitHub
parent 80f5018924
commit ad05924bdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 28 deletions

View File

@ -4,32 +4,13 @@ module Chat
module MessagesExporter module MessagesExporter
LIMIT = 10_000 LIMIT = 10_000
def chat_message_export def chat_message_export(&block)
Chat::Message # perform 1 db query per month:
.unscoped now = Time.now
.where(created_at: 6.months.ago..Time.current) from = 6.months.ago
.includes(:chat_channel) while from <= now
.includes(:user) export(from, from + 1.month, &block)
.includes(:last_editor) from = from + 1.month
.limit(LIMIT)
.find_each do |chat_message|
yield(
[
chat_message.id,
chat_message.chat_channel.id,
chat_message.chat_channel.name,
chat_message.user.id,
chat_message.user.username,
chat_message.message,
chat_message.cooked,
chat_message.created_at,
chat_message.updated_at,
chat_message.deleted_at,
chat_message.in_reply_to&.id,
chat_message.last_editor&.id,
chat_message.last_editor&.username,
]
)
end end
end end
@ -54,5 +35,36 @@ module Chat
super super
end end
end end
private
def export(from, to)
Chat::Message
.unscoped
.where(created_at: from..to)
.includes(:chat_channel)
.includes(:user)
.includes(:last_editor)
.limit(LIMIT)
.find_each do |chat_message|
yield(
[
chat_message.id,
chat_message.chat_channel.id,
chat_message.chat_channel.name,
chat_message.user.id,
chat_message.user.username,
chat_message.message,
chat_message.cooked,
chat_message.created_at,
chat_message.updated_at,
chat_message.deleted_at,
chat_message.in_reply_to&.id,
chat_message.last_editor&.id,
chat_message.last_editor&.username,
]
)
end
end
end end
end end

View File

@ -11,7 +11,10 @@ RSpec.describe "Chat CSV exports", type: :system do
end end
xit "exports chat messages" do xit "exports chat messages" do
message = Fabricate(:chat_message) message_1 = Fabricate(:chat_message, created_at: 12.months.ago)
message_2 = Fabricate(:chat_message, created_at: 6.months.ago)
message_3 = Fabricate(:chat_message, created_at: 1.months.ago)
message_4 = Fabricate(:chat_message, created_at: Time.now)
visit "/admin/plugins/chat" visit "/admin/plugins/chat"
click_button "Create export" click_button "Create export"
@ -39,8 +42,17 @@ RSpec.describe "Chat CSV exports", type: :system do
], ],
) )
assert_message(exported_data.second, message_1)
assert_message(exported_data.third, message_2)
assert_message(exported_data.fourth, message_3)
assert_message(exported_data.fifth, message_4)
ensure
csv_export_pm_page.clear_downloads
end
def assert_message(exported_message, message)
time_format = "%Y-%m-%d %H:%M:%S UTC" time_format = "%Y-%m-%d %H:%M:%S UTC"
expect(exported_data.second).to eq( expect(exported_message).to eq(
[ [
message.id.to_s, message.id.to_s,
message.chat_channel.id.to_s, message.chat_channel.id.to_s,
@ -57,7 +69,5 @@ RSpec.describe "Chat CSV exports", type: :system do
message.last_editor.username, message.last_editor.username,
], ],
) )
ensure
csv_export_pm_page.clear_downloads
end end
end end