[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 time import strftime, strptime
from datetime import timedelta
from datetime import timedelta, datetime
import pytz
import vobject
from odoorpc import ODOO
@ -88,8 +88,9 @@ class Collection(BaseCollection):
self.is_principal = len(attributes) == 0
@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 """
date_obj = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S')
local_date = cls.server_timezone.localize(date_obj, is_dst=None)
return local_date.astimezone(pytz.utc)
@ -155,6 +156,17 @@ class Collection(BaseCollection):
def get_events_from_odoo(cls, login, path):
""" Gets all events available from one Odoo 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
if path.endswith('odoo-calendar-own'):
domain = [('user_id', '=', cls.odoo.env.uid)]
@ -164,10 +176,12 @@ class Collection(BaseCollection):
domain = [('partner_ids', '=', pid)]
else:
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...
# 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):
""" Debug purpose """
@ -240,35 +254,41 @@ class Collection(BaseCollection):
return vobject_item
@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 """
# TODO/IMP : attendees management (not handled directly by vobject)
if event.allday:
utc_dtstart = event.start_date
utc_dtstop = event.stop_date + timedelta(days=1)
event = cls.events.get(database_id)
if event.get('allday'):
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:
utc_dtstart = cls.odoo_date_to_utc(event.start_datetime)
utc_dtstop = cls.odoo_date_to_utc(event.stop_datetime)
last_modified = str(cls.odoo_date_to_utc(event.write_date))
utc_dtstart = cls.odoo_date_to_utc(event.get('start_datetime'))
utc_dtstop = cls.odoo_date_to_utc(event.get('stop_datetime'))
last_modified = str(cls.odoo_date_to_utc(event.get('write_date')))
cal = vobject.iCalendar()
cal.add('vevent')
cal.vevent.add('summary').value = event.name
cal.vevent.add('location').value = event.location or ''
cal.vevent.add('description').value = event.description or ''
cal.vevent.add('summary').value = event.get('name')
cal.vevent.add('location').value = event.get('location') or ''
cal.vevent.add('description').value = event.get('description') or ''
cal.vevent.add('dtstart').value = utc_dtstart
cal.vevent.add('dtend').value = utc_dtstop
# cal.vevent.add('duration').value = event.duration
if event.categ_ids:
categs = [categ.name for categ in event.categ_ids]
if event.get('categ_ids'):
categs = [cls.event_types.get(etid) for etid in event.get('categ_ids')]
cal.vevent.add('categories').value = categs
if event.alarm_ids:
for alarm in event.alarm_ids:
if event.get('alarm_ids'):
for alarm_id in event.get('alarm_ids'):
alarm = cls.event_alarms.get(alarm_id)
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('trigger').value = timedelta(minutes=-alarm.duration_minutes)
if event.recurrency:
cal.vevent.add('rrule').value = event.rrule
valarm.add('trigger').value = timedelta(
minutes=-alarm.get('duration_minutes'))
if event.get('recurrency'):
cal.vevent.add('rrule').value = event.get('rrule')
cal.vevent.add('uid').value = href
cal.vevent.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)
return self._get_item_from_vobject(href, vobject_item)
elif model == 'calendar.event':
record = self.odoo.env[model].browse([database_id])
vobject_item = self._generate_ics_from_odoo(href, record)
vobject_item = self._generate_ics_from_odoo(href, database_id)
return self._get_item_from_vobject(href, vobject_item)
else:
raise NotImplementedError