mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-21 03:12:10 +02:00
82 lines
3.6 KiB
Python
82 lines
3.6 KiB
Python
import datetime
|
|
|
|
from odoo.tools import SQL, config, lazy_classproperty
|
|
from odoo.tools.constants import GC_UNLINK_LIMIT
|
|
|
|
from . import decorators as api
|
|
from .models import Model
|
|
|
|
|
|
class TransientModel(Model):
|
|
""" Model super-class for transient records, meant to be temporarily
|
|
persistent, and regularly vacuum-cleaned.
|
|
|
|
A TransientModel has a simplified access rights management, all users can
|
|
create new records, and may only access the records they created. The
|
|
superuser has unrestricted access to all TransientModel records.
|
|
"""
|
|
_auto: bool = True # automatically create database backend
|
|
_register: bool = False # not visible in ORM registry, meant to be python-inherited only
|
|
_abstract = False # not abstract
|
|
_transient = True # transient
|
|
|
|
# default values for _transient_vacuum()
|
|
_transient_max_count = lazy_classproperty(lambda _: int(config.get('osv_memory_count_limit')))
|
|
"maximum number of transient records, unlimited if ``0``"
|
|
_transient_max_hours = lazy_classproperty(lambda _: float(config.get('transient_age_limit')))
|
|
"maximum idle lifetime (in hours), unlimited if ``0``"
|
|
|
|
@api.autovacuum
|
|
def _transient_vacuum(self):
|
|
"""Clean the transient records.
|
|
|
|
This unlinks old records from the transient model tables whenever the
|
|
:attr:`_transient_max_count` or :attr:`_transient_max_hours` conditions
|
|
(if any) are reached.
|
|
|
|
Actual cleaning will happen only once every 5 minutes. This means this
|
|
method can be called frequently (e.g. whenever a new record is created).
|
|
|
|
Example with both max_hours and max_count active:
|
|
|
|
Suppose max_hours = 0.2 (aka 12 minutes), max_count = 20, there are
|
|
55 rows in the table, 10 created/changed in the last 5 minutes, an
|
|
additional 12 created/changed between 5 and 10 minutes ago, the rest
|
|
created/changed more than 12 minutes ago.
|
|
|
|
- age based vacuum will leave the 22 rows created/changed in the last 12
|
|
minutes
|
|
- count based vacuum will wipe out another 12 rows. Not just 2,
|
|
otherwise each addition would immediately cause the maximum to be
|
|
reached again.
|
|
- the 10 rows that have been created/changed the last 5 minutes will NOT
|
|
be deleted
|
|
"""
|
|
has_remaining = False
|
|
if self._transient_max_hours:
|
|
# Age-based expiration
|
|
has_remaining |= self._transient_clean_rows_older_than(self._transient_max_hours * 60 * 60)
|
|
|
|
if self._transient_max_count:
|
|
# Count-based expiration
|
|
has_remaining |= self._transient_clean_old_rows(self._transient_max_count)
|
|
# This method is shared by all transient models therefore,
|
|
# return the model name to be logged and if whether there are more rows to process
|
|
return self._name, has_remaining
|
|
|
|
def _transient_clean_old_rows(self, max_count: int) -> bool:
|
|
# Check how many rows we have in the table
|
|
self._cr.execute(SQL("SELECT count(*) FROM %s", SQL.identifier(self._table)))
|
|
[count] = self._cr.fetchone()
|
|
if count > max_count:
|
|
return self._transient_clean_rows_older_than(300)
|
|
return False
|
|
|
|
def _transient_clean_rows_older_than(self, seconds: int) -> bool:
|
|
# Never delete rows used in last 5 minutes
|
|
seconds = max(seconds, 300)
|
|
now = self.env.cr.now()
|
|
domain = [('write_date', '<', now - datetime.timedelta(seconds=seconds))]
|
|
records = self.sudo().search(domain, limit=GC_UNLINK_LIMIT)
|
|
records.unlink()
|
|
return len(records) == GC_UNLINK_LIMIT
|