PERF: removed N*2+1 in availability topic (#599)
WE "recently" did a few changes in the way we use the availability topic - We used to have 1 topic per year, but have now moved to just using one topic and deleted past posts - We used to delete past automatic holidays, but we don't anymore since we use them to keep track of #leave days used - There are more employees covering more regions All three changes made the query that list all the events to be displayed in the availability topic go 💥 It used to be - 1 query to list all events from 6 months ago up to 6 months in the future - 1 query for every events to load the associated user - 1 query for every events to load the associated's user timezone So basically, a N*2 + 1 😅 This commit fixes the issue by doing - 1 query to get all "standalone" events (those associated to a post) - 1 query to get all the users timezones (just the ones who have an holiday in the current period). - 1 query to get all the "automatic" events (aka. holidays that are comming from the holidays gem). So we went from N*2 + 1 down to 3 🚀
This commit is contained in:
parent
d6ad7349f2
commit
f268eccaa0
103
plugin.rb
103
plugin.rb
|
|
@ -358,52 +358,81 @@ after_initialize do
|
|||
end
|
||||
|
||||
add_to_serializer(:post, :calendar_details, include_condition: -> { object.is_first_post? }) do
|
||||
grouped = {}
|
||||
standalones = []
|
||||
start_date = 6.months.ago
|
||||
|
||||
CalendarEvent
|
||||
.where(topic_id: object.topic_id)
|
||||
.where("post_id IS NOT NULL OR start_date >= ?", 6.months.ago)
|
||||
.order(:start_date, :end_date)
|
||||
.each do |event|
|
||||
if event.post_id
|
||||
standalones << {
|
||||
standalone_sql = <<~SQL
|
||||
SELECT post_number, description, start_date, end_date, username, recurrence, timezone
|
||||
FROM calendar_events
|
||||
WHERE topic_id = :topic_id
|
||||
AND post_id IS NOT NULL
|
||||
ORDER BY start_date, end_date
|
||||
SQL
|
||||
|
||||
standalones =
|
||||
DB
|
||||
.query(standalone_sql, topic_id: object.topic_id)
|
||||
.map do |row|
|
||||
{
|
||||
type: :standalone,
|
||||
post_number: event.post_number,
|
||||
message: event.description,
|
||||
from: event.start_date,
|
||||
to: event.end_date,
|
||||
username: event.username,
|
||||
recurring: event.recurrence,
|
||||
post_url: Post.url("-", event.topic_id, event.post_number),
|
||||
timezone: event.timezone,
|
||||
}
|
||||
else
|
||||
identifier = "#{event.region.split("_").first}-#{event.start_date.strftime("%Y-%j")}"
|
||||
|
||||
grouped[identifier] ||= {
|
||||
type: :grouped,
|
||||
from: event.start_date,
|
||||
timezone: event.timezone,
|
||||
name: [],
|
||||
users: [],
|
||||
}
|
||||
|
||||
user = User.find_by_username(event.username)
|
||||
|
||||
grouped[identifier][:name] << event.description
|
||||
grouped[identifier][:users] << {
|
||||
username: event.username,
|
||||
timezone: user.present? ? user.user_option.timezone : nil,
|
||||
post_number: row.post_number,
|
||||
message: row.description,
|
||||
from: row.start_date,
|
||||
to: row.end_date,
|
||||
username: row.username,
|
||||
recurring: row.recurrence,
|
||||
post_url: Post.url("-", object.topic_id, row.post_number),
|
||||
timezone: row.timezone,
|
||||
}
|
||||
end
|
||||
|
||||
timezones =
|
||||
UserOption
|
||||
.where(
|
||||
user_id:
|
||||
CalendarEvent.where(
|
||||
topic_id: object.topic_id,
|
||||
post_id: nil,
|
||||
start_date: start_date..,
|
||||
).select(:user_id),
|
||||
)
|
||||
.where("LENGTH(COALESCE(timezone, '')) > 0")
|
||||
.pluck(:user_id, :timezone)
|
||||
.to_h
|
||||
|
||||
grouped = {}
|
||||
|
||||
grouped_sql = <<~SQL
|
||||
SELECT region, start_date, timezone, user_id, username, description
|
||||
FROM calendar_events
|
||||
WHERE topic_id = :topic_id
|
||||
AND post_id IS NULL
|
||||
AND start_date >= :start_date
|
||||
ORDER BY region, start_date
|
||||
SQL
|
||||
|
||||
DB
|
||||
.query(grouped_sql, topic_id: object.topic_id, start_date: start_date)
|
||||
.each do |row|
|
||||
identifier = "#{row.region.split("_").first}-#{row.start_date.strftime("%Y-%j")}"
|
||||
|
||||
grouped[identifier] ||= {
|
||||
type: :grouped,
|
||||
from: row.start_date,
|
||||
timezone: row.timezone,
|
||||
name: [],
|
||||
users: [],
|
||||
}
|
||||
|
||||
grouped[identifier][:name] << row.description
|
||||
grouped[identifier][:users] << { username: row.username, timezone: timezones[row.user_id] }
|
||||
end
|
||||
|
||||
grouped.each do |_, v|
|
||||
v[:name].sort!.uniq!
|
||||
v[:name].uniq!
|
||||
v[:name].sort!
|
||||
v[:name] = v[:name].join(", ")
|
||||
v[:users].sort! { |a, b| a[:username] <=> b[:username] }
|
||||
v[:users].uniq! { |u| u[:username] }
|
||||
v[:users].sort! { |a, b| a[:username] <=> b[:username] }
|
||||
end
|
||||
|
||||
standalones + grouped.values
|
||||
|
|
|
|||
Loading…
Reference in New Issue