Merge lp:~therp-nl/openobject-server/ronald@therp.nl_6.1_lp1009014_new-6.1 into lp:openobject-server/6.1

Proposed by Ronald Portier (Therp)
Status: Needs review
Proposed branch: lp:~therp-nl/openobject-server/ronald@therp.nl_6.1_lp1009014_new-6.1
Merge into: lp:openobject-server/6.1
Diff against target: 78 lines (+31/-18)
1 file modified
openerp/osv/orm.py (+31/-18)
To merge this branch: bzr merge lp:~therp-nl/openobject-server/ronald@therp.nl_6.1_lp1009014_new-6.1
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+131201@code.launchpad.net

Description of the change

Fix vacuum cleaning on transient object.

This is a new proposal taking into account the remarks made by Vo Minh Thu.

To post a comment you must log in.

Unmerged revisions

4290. By Ronald Portier (Therp)

[FIX] Fix vacuum cleaning both for time and count based cleaning,
      adding a safeguard against cleaning recently used rows.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openerp/osv/orm.py'
2--- openerp/osv/orm.py 2012-09-24 14:00:07 +0000
3+++ openerp/osv/orm.py 2012-10-24 14:59:30 +0000
4@@ -674,9 +674,6 @@
5
6 # Transience
7 _transient = False # True in a TransientModel
8- _transient_max_count = None
9- _transient_max_hours = None
10- _transient_check_time = 20
11
12 # structure:
13 # { 'parent_model': 'm2o_field', ... }
14@@ -4889,20 +4886,26 @@
15
16 def _transient_clean_rows_older_than(self, cr, seconds):
17 assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name
18- cr.execute("SELECT id FROM " + self._table + " WHERE"
19- " COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp <"
20- " ((now() at time zone 'UTC') - interval %s)", ("%s seconds" % seconds,))
21- ids = [x[0] for x in cr.fetchall()]
22- self.unlink(cr, SUPERUSER_ID, ids)
23-
24- def _transient_clean_old_rows(self, cr, count):
25- assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name
26+ '''Never delete rows used in last 5 minutes'''
27+ seconds = max(seconds, 300)
28+ now_str = "(now() at time zone 'UTC')"
29 cr.execute(
30- "SELECT id, COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp"
31- " AS t FROM " + self._table +
32- " ORDER BY t LIMIT %s", (count,))
33+ "SELECT id FROM " + self._table + " WHERE"
34+ " COALESCE(write_date, create_date, " + now_str + ")::timestamp"
35+ "< (" + now_str + " - interval %s)", ("%s seconds" % seconds,))
36 ids = [x[0] for x in cr.fetchall()]
37- self.unlink(cr, SUPERUSER_ID, ids)
38+ if ids:
39+ self.unlink(cr, SUPERUSER_ID, ids)
40+
41+ def _transient_clean_old_rows(self, cr, max_count):
42+ # Check how many rows we have in the table
43+ sql_statement = "SELECT count(*) as row_count FROM %s" % (self._table, )
44+ cr.execute(sql_statement)
45+ res = cr.fetchall()
46+ row_count = res[0][0]
47+ if row_count <= max_count:
48+ return # max not reached, nothing to do
49+ self._transient_clean_rows_older_than(cr, 300)
50
51 def _transient_vacuum(self, cr, uid, force=False):
52 """Clean the transient records.
53@@ -4912,12 +4915,22 @@
54 Actual cleaning will happen only once every "_transient_check_time" calls.
55 This means this method can be called frequently called (e.g. whenever
56 a new record is created).
57+ Example with both max_hours and max_count active:
58+ Suppose max_hours = 0.2 (e.g. 12 minutes), max_count = 20, there are 55 rows in the
59+ table, 10 created/changed in the last 5 minutes, an additional 12 created/changed between
60+ 5 and 10 minutes ago, the rest created/changed more then 12 minutes ago.
61+ - age based vacuum will leave the 22 rows created/changed in the last 12 minutes
62+ - count based vacuum will wipe out another 12 rows. Not just 2, otherwise each addition
63+ would immediately cause the maximum to be reached again.
64+ - the 10 rows that have been created/changed the last 5 minutes will NOT be deleted
65 """
66 assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name
67+ _transient_check_time = 20 # arbitrary limit on vacuum executions
68 self._transient_check_count += 1
69- if (not force) and (self._transient_check_count % self._transient_check_time):
70- self._transient_check_count = 0
71- return True
72+ if ((not force)
73+ and (self._transient_check_count < _transient_check_time)):
74+ return True # no vacuum cleaning this time
75+ self._transient_check_count = 0
76
77 # Age-based expiration
78 if self._transient_max_hours: