[PERF]Radicale Odoo Storage : huge performance optimization for events too

This commit is contained in:
Fabien BOURGEOIS 2018-05-13 09:01:01 +02:00
parent 15cf112cc3
commit 7b82b4c2d4
1 changed files with 43 additions and 24 deletions

View File

@ -32,7 +32,7 @@
from contextlib import contextmanager from contextlib import contextmanager
from time import strftime, strptime from time import strftime, strptime
from datetime import timedelta from datetime import timedelta, datetime
import pytz import pytz
import vobject import vobject
from odoorpc import ODOO from odoorpc import ODOO
@ -88,8 +88,9 @@ class Collection(BaseCollection):
self.is_principal = len(attributes) == 0 self.is_principal = len(attributes) == 0
@classmethod @classmethod
def odoo_date_to_utc(cls, date_obj): def odoo_date_to_utc(cls, date_str):
""" Transform naive Odoo date object to UTC TZ """ """ Transform naive Odoo date object to UTC TZ """
date_obj = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S')
local_date = cls.server_timezone.localize(date_obj, is_dst=None) local_date = cls.server_timezone.localize(date_obj, is_dst=None)
return local_date.astimezone(pytz.utc) return local_date.astimezone(pytz.utc)
@ -155,6 +156,17 @@ class Collection(BaseCollection):
def get_events_from_odoo(cls, login, path): def get_events_from_odoo(cls, login, path):
""" Gets all events available from one Odoo login """ """ Gets all events available from one Odoo login """
cls.logger.info('Get events for Odoo user %s' % login) cls.logger.info('Get events for Odoo user %s' % login)
fields = ['allday', 'start_date', 'stop_date', 'start_datetime',
'stop_datetime', 'write_date', 'name', 'location',
'description', 'recurrency', 'rrule', 'categ_ids', 'alarm_ids']
event_types = cls.odoo.execute_kw('calendar.event.type', 'search_read',
[[]], {'fields': ['name']})
cls.event_types = {et['id']: et['name'] for et in event_types}
event_alarms = cls.odoo.execute_kw('calendar.alarm', 'search_read',
[[]], {'fields': ['type',
'duration_minutes']})
cls.event_alarms = {ea['id']: ea for ea in event_alarms}
cls.odoo.env.context.update({'virtual_id': False}) # Only real events cls.odoo.env.context.update({'virtual_id': False}) # Only real events
if path.endswith('odoo-calendar-own'): if path.endswith('odoo-calendar-own'):
domain = [('user_id', '=', cls.odoo.env.uid)] domain = [('user_id', '=', cls.odoo.env.uid)]
@ -164,10 +176,12 @@ class Collection(BaseCollection):
domain = [('partner_ids', '=', pid)] domain = [('partner_ids', '=', pid)]
else: else:
domain = [] domain = []
event_ids = cls.odoo.env['calendar.event'].search(domain) events = cls.odoo.execute_kw('calendar.event', 'search_read',
[domain], {'fields': fields})
cls.events = {e['id']: e for e in events}
# WARNING: Odoo does not remove from database deleted recurrent events... # WARNING: Odoo does not remove from database deleted recurrent events...
# Should be fixed on Odoo side and will be fixed via 2way here too # Should be fixed on Odoo side and will be fixed via 2way here too
return ['calendar.event:%s' % eid for eid in event_ids] return ['calendar.event:%s' % eid for eid in cls.events.keys()]
def sync(self, old_token=None): def sync(self, old_token=None):
""" Debug purpose """ """ Debug purpose """
@ -240,35 +254,41 @@ class Collection(BaseCollection):
return vobject_item return vobject_item
@classmethod @classmethod
def _generate_ics_from_odoo(cls, href, event): def _generate_ics_from_odoo(cls, href, database_id):
""" Generate and return UCS object from Odoo calendar.event record """ """ Generate and return UCS object from Odoo calendar.event record """
# TODO/IMP : attendees management (not handled directly by vobject) # TODO/IMP : attendees management (not handled directly by vobject)
if event.allday: event = cls.events.get(database_id)
utc_dtstart = event.start_date if event.get('allday'):
utc_dtstop = event.stop_date + timedelta(days=1) utc_dtstart = datetime.strptime(event.get('start_date'),
'%Y-%m-%d').date()
stop_date_obj = datetime.strptime(event.get('stop_date'),
'%Y-%m-%d').date()
utc_dtstop = stop_date_obj + timedelta(days=1)
else: else:
utc_dtstart = cls.odoo_date_to_utc(event.start_datetime) utc_dtstart = cls.odoo_date_to_utc(event.get('start_datetime'))
utc_dtstop = cls.odoo_date_to_utc(event.stop_datetime) utc_dtstop = cls.odoo_date_to_utc(event.get('stop_datetime'))
last_modified = str(cls.odoo_date_to_utc(event.write_date)) last_modified = str(cls.odoo_date_to_utc(event.get('write_date')))
cal = vobject.iCalendar() cal = vobject.iCalendar()
cal.add('vevent') cal.add('vevent')
cal.vevent.add('summary').value = event.name cal.vevent.add('summary').value = event.get('name')
cal.vevent.add('location').value = event.location or '' cal.vevent.add('location').value = event.get('location') or ''
cal.vevent.add('description').value = event.description or '' cal.vevent.add('description').value = event.get('description') or ''
cal.vevent.add('dtstart').value = utc_dtstart cal.vevent.add('dtstart').value = utc_dtstart
cal.vevent.add('dtend').value = utc_dtstop cal.vevent.add('dtend').value = utc_dtstop
# cal.vevent.add('duration').value = event.duration # cal.vevent.add('duration').value = event.duration
if event.categ_ids: if event.get('categ_ids'):
categs = [categ.name for categ in event.categ_ids] categs = [cls.event_types.get(etid) for etid in event.get('categ_ids')]
cal.vevent.add('categories').value = categs cal.vevent.add('categories').value = categs
if event.alarm_ids: if event.get('alarm_ids'):
for alarm in event.alarm_ids: for alarm_id in event.get('alarm_ids'):
alarm = cls.event_alarms.get(alarm_id)
valarm = cal.vevent.add('valarm') valarm = cal.vevent.add('valarm')
action = 'DISPLAY' if alarm.type == 'notification' else 'EMAIL' action = 'DISPLAY' if alarm.get('type') == 'notification' else 'EMAIL'
valarm.add('action').value = action valarm.add('action').value = action
valarm.add('trigger').value = timedelta(minutes=-alarm.duration_minutes) valarm.add('trigger').value = timedelta(
if event.recurrency: minutes=-alarm.get('duration_minutes'))
cal.vevent.add('rrule').value = event.rrule if event.get('recurrency'):
cal.vevent.add('rrule').value = event.get('rrule')
cal.vevent.add('uid').value = href cal.vevent.add('uid').value = href
cal.vevent.add('rev').value = last_modified cal.vevent.add('rev').value = last_modified
cal.add('rev').value = last_modified cal.add('rev').value = last_modified
@ -294,8 +314,7 @@ class Collection(BaseCollection):
vobject_item = self._generate_vcard_from_odoo(database_id) vobject_item = self._generate_vcard_from_odoo(database_id)
return self._get_item_from_vobject(href, vobject_item) return self._get_item_from_vobject(href, vobject_item)
elif model == 'calendar.event': elif model == 'calendar.event':
record = self.odoo.env[model].browse([database_id]) vobject_item = self._generate_ics_from_odoo(href, database_id)
vobject_item = self._generate_ics_from_odoo(href, record)
return self._get_item_from_vobject(href, vobject_item) return self._get_item_from_vobject(href, vobject_item)
else: else:
raise NotImplementedError raise NotImplementedError