summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Martinelli <nim@odoo.com>2018-04-17 19:02:10 +0200
committerNicolas Martinelli <nim-odoo@users.noreply.github.com>2018-04-18 08:17:50 +0200
commitffdfbed42c48a4b85c26f224f32003b8bda2ce78 (patch)
treeb0d06e11fc3a8121778a6c19f275fbfb46372872
parentb15e805b5ad40e1e8e08e9be1ba248da66158bc9 (diff)
[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
-rw-r--r--addons/calendar/models/calendar.py22
1 files changed, 15 insertions, 7 deletions
diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py
index f105ea7095c..4d377e295d8 100644
--- a/addons/calendar/models/calendar.py
+++ b/addons/calendar/models/calendar.py
@@ -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