[FIX] calendar: avoid memory overflow

On a DB with thousands of events including recurring ones, fetching the
complete list of events might lead to a memory overflow due to the
prefetching of all virtual events.

We reduce the memory footprint by handling no more than 50,000 records
at a time and clearing the cache at each step. This limit is purely
arbitrary, but seems to be a good compromise between performance and
memory usage.

opw-1832482
This commit is contained in:
Nicolas Martinelli
2018-04-18 08:17:50 +02:00
committed by Nicolas Martinelli
parent b15e805b5a
commit ffdfbed42c
+15 -7
View File
@@ -617,13 +617,21 @@ class Meeting(models.Model):
event_date = event_date.astimezone(timezone) # transform "+hh:mm" timezone
rset1 = rrule.rrulestr(str(self.rrule), dtstart=event_date, forceset=True, tzinfos={})
recurring_meetings = self.search([('recurrent_id', '=', self.id), '|', ('active', '=', False), ('active', '=', True)])
for meeting in recurring_meetings:
recurring_date = fields.Datetime.from_string(meeting.recurrent_id_date)
if use_naive_datetime:
recurring_date = recurring_date.replace(tzinfo=None)
else:
recurring_date = todate(meeting.recurrent_id_date)
rset1.exdate(recurring_date)
# We handle a maximum of 50,000 meetings at a time, and clear the cache at each step to
# control the memory usage.
invalidate = False
for meetings in self.env.cr.split_for_in_conditions(recurring_meetings, size=50000):
if invalidate:
self.invalidate_cache()
for meeting in meetings:
recurring_date = fields.Datetime.from_string(meeting.recurrent_id_date)
if use_naive_datetime:
recurring_date = recurring_date.replace(tzinfo=None)
else:
recurring_date = todate(meeting.recurrent_id_date)
rset1.exdate(recurring_date)
invalidate = True
return [d.astimezone(pytz.UTC) if d.tzinfo else d for d in rset1]
@api.multi