[IMP] gamification: performance improvement
Reduce the number of goals that are recomputed. Remove the goals for users that did not connect since the last update. Add sql query for faster lookup and restrict on user table
This commit is contained in:
parent
fb8dc5793b
commit
ec0c0f2973
|
@ -300,18 +300,23 @@ class gamification_challenge(osv.Model):
|
|||
|
||||
goal_obj = self.pool.get('gamification.goal')
|
||||
|
||||
# we use yesterday to update the goals that just ended
|
||||
# include yesterday goals to update the goals that just ended
|
||||
# exclude goals for users that did not connect since the last update
|
||||
yesterday = date.today() - timedelta(days=1)
|
||||
goal_ids = goal_obj.search(cr, uid, [
|
||||
('challenge_id', 'in', ids),
|
||||
'|',
|
||||
('state', '=', 'inprogress'),
|
||||
'&',
|
||||
('state', 'in', ('reached', 'failed')),
|
||||
'|',
|
||||
('end_date', '>=', yesterday.strftime(DF)),
|
||||
('end_date', '=', False)
|
||||
], context=context)
|
||||
cr.execute("""SELECT gg.id
|
||||
FROM gamification_goal as gg,
|
||||
gamification_challenge as gc,
|
||||
res_users as ru
|
||||
WHERE gg.challenge_id = gc.id
|
||||
AND gg.user_id = ru.id
|
||||
AND gg.write_date < ru.login_date
|
||||
AND gg.closed IS false
|
||||
AND gc.id IN %s
|
||||
AND (gg.state = 'inprogress'
|
||||
OR (gg.state = 'reached'
|
||||
AND (gg.end_date >= %s OR gg.end_date IS NULL)))
|
||||
""", (tuple(ids), yesterday.strftime(DF)))
|
||||
goal_ids = cr.fetchall()
|
||||
# update every running goal already generated linked to selected challenges
|
||||
goal_obj.update(cr, uid, goal_ids, context=context)
|
||||
|
||||
|
|
|
@ -268,6 +268,25 @@ class gamification_goal(osv.Model):
|
|||
return {'to_update': True}
|
||||
return {}
|
||||
|
||||
def _get_write_values(self, cr, uid, goal, new_value, context=None):
|
||||
"""Generate values to write after recomputation of a goal score"""
|
||||
if new_value == goal.current:
|
||||
# avoid useless write if the new value is the same as the old one
|
||||
return {}
|
||||
|
||||
result = {goal.id: {'current': new_value}}
|
||||
if (goal.definition_id.condition == 'higher' and new_value >= goal.target_goal) \
|
||||
or (goal.definition_id.condition == 'lower' and new_value <= goal.target_goal):
|
||||
# success, do no set closed as can still change
|
||||
result[goal.id]['state'] = 'reached'
|
||||
|
||||
elif goal.end_date and fields.date.today() > goal.end_date:
|
||||
# check goal failure
|
||||
result[goal.id]['state'] = 'failed'
|
||||
result[goal.id]['closed'] = True
|
||||
|
||||
return result
|
||||
|
||||
def update(self, cr, uid, ids, context=None):
|
||||
"""Update the goals to recomputes values and change of states
|
||||
|
||||
|
@ -281,14 +300,8 @@ class gamification_goal(osv.Model):
|
|||
commit = context.get('commit_gamification', False)
|
||||
|
||||
goals_by_definition = {}
|
||||
all_goals = {}
|
||||
for goal in self.browse(cr, uid, ids, context=context):
|
||||
if goal.state in ('draft', 'canceled'):
|
||||
# draft or canceled goals should not be recomputed
|
||||
continue
|
||||
|
||||
goals_by_definition.setdefault(goal.definition_id, []).append(goal)
|
||||
all_goals[goal.id] = goal
|
||||
|
||||
for definition, goals in goals_by_definition.items():
|
||||
goals_to_write = dict((goal.id, {}) for goal in goals)
|
||||
|
@ -313,8 +326,10 @@ class gamification_goal(osv.Model):
|
|||
# the result of the evaluated codeis put in the 'result' local variable, propagated to the context
|
||||
result = cxt.get('result')
|
||||
if result is not None and type(result) in (float, int, long):
|
||||
if result != goal.current:
|
||||
goals_to_write[goal.id]['current'] = result
|
||||
goals_to_write.update(
|
||||
self._get_write_values(cr, uid, goal, result, context=context)
|
||||
)
|
||||
|
||||
else:
|
||||
_logger.exception(_('Invalid return content from the evaluation of code for definition %s') % definition.name)
|
||||
|
||||
|
@ -356,8 +371,9 @@ class gamification_goal(osv.Model):
|
|||
queried_value = queried_value[0]
|
||||
if queried_value == query_goals[goal.id]:
|
||||
new_value = user_value.get(field_name+'_count', goal.current)
|
||||
if new_value != goal.current:
|
||||
goals_to_write[goal.id]['current'] = new_value
|
||||
goals_to_write.update(
|
||||
self._get_write_values(cr, uid, goal, new_value, context=context)
|
||||
)
|
||||
|
||||
else:
|
||||
for goal in goals:
|
||||
|
@ -379,26 +395,14 @@ class gamification_goal(osv.Model):
|
|||
else: # computation mode = count
|
||||
new_value = obj.search(cr, uid, domain, context=context, count=True)
|
||||
|
||||
# avoid useless write if the new value is the same as the old one
|
||||
if new_value != goal.current:
|
||||
goals_to_write[goal.id]['current'] = new_value
|
||||
goals_to_write.update(
|
||||
self._get_write_values(cr, uid, goal, new_value, context=context)
|
||||
)
|
||||
|
||||
for goal_id, value in goals_to_write.items():
|
||||
if not value:
|
||||
continue
|
||||
goal = all_goals[goal_id]
|
||||
|
||||
# check goal target reached
|
||||
if (goal.definition_id.condition == 'higher' and value.get('current', goal.current) >= goal.target_goal) \
|
||||
or (goal.definition_id.condition == 'lower' and value.get('current', goal.current) <= goal.target_goal):
|
||||
value['state'] = 'reached'
|
||||
|
||||
# check goal failure
|
||||
elif goal.end_date and fields.date.today() > goal.end_date:
|
||||
value['state'] = 'failed'
|
||||
value['closed'] = True
|
||||
if value:
|
||||
self.write(cr, uid, [goal.id], value, context=context)
|
||||
self.write(cr, uid, [goal_id], value, context=context)
|
||||
if commit:
|
||||
cr.commit()
|
||||
return True
|
||||
|
|
Loading…
Reference in New Issue