Manage Cache in Transaction
issue6216 review33021002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Manage Cache in Transaction
|
||||
* Allow to register multiple exit functions on Transaction
|
||||
* Return 429 status when too many login attempts
|
||||
* Add set_rpc on Field
|
||||
|
||||
@@ -13,6 +13,8 @@ be unique and it's used to identify the cache. We usually use
|
||||
be used to limit the number of values cached and the `context` parameter
|
||||
is used to indicate if the cache depends on the user context and is true
|
||||
by default.
|
||||
The cache is cleaned on :class:`Transaction` starts and resets on
|
||||
:class:`Transaction` commit or rollback.
|
||||
|
||||
.. warning::
|
||||
As there is no deepcopy of the values cached, they must never be mutated
|
||||
|
||||
+2
-2
@@ -105,7 +105,7 @@ class MemoryCache(BaseCache):
|
||||
|
||||
@staticmethod
|
||||
def clean(dbname):
|
||||
with Transaction().new_transaction() as transaction,\
|
||||
with Transaction().new_transaction(_nocache=True) as transaction,\
|
||||
transaction.connection.cursor() as cursor:
|
||||
table = Table('ir_cache')
|
||||
cursor.execute(*table.select(table.timestamp, table.name))
|
||||
@@ -129,7 +129,7 @@ class MemoryCache(BaseCache):
|
||||
@staticmethod
|
||||
def resets(dbname):
|
||||
table = Table('ir_cache')
|
||||
with Transaction().new_transaction() as transaction,\
|
||||
with Transaction().new_transaction(_nocache=True) as transaction,\
|
||||
transaction.connection.cursor() as cursor,\
|
||||
Cache._resets_lock:
|
||||
Cache._resets.setdefault(dbname, set())
|
||||
|
||||
@@ -14,7 +14,6 @@ from ..transaction import Transaction
|
||||
from ..pool import Pool
|
||||
from .. import backend
|
||||
from ..config import config
|
||||
from ..cache import Cache
|
||||
from ..sendmail import sendmail
|
||||
|
||||
__all__ = [
|
||||
@@ -181,7 +180,6 @@ class Cron(ModelSQL, ModelView):
|
||||
def run(cls, db_name):
|
||||
now = datetime.datetime.now()
|
||||
with Transaction().start(db_name, 0) as transaction:
|
||||
Cache.clean(db_name)
|
||||
transaction.database.lock(transaction.connection, cls._table)
|
||||
crons = cls.search([
|
||||
('number_calls', '!=', 0),
|
||||
@@ -214,4 +212,3 @@ class Cron(ModelSQL, ModelView):
|
||||
except Exception:
|
||||
transaction.rollback()
|
||||
logger.error('Running cron %s', cron.id, exc_info=True)
|
||||
Cache.resets(db_name)
|
||||
|
||||
@@ -17,7 +17,6 @@ from sql.functions import CurrentTimestamp
|
||||
import trytond.tools as tools
|
||||
from trytond.config import config
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond import backend
|
||||
import trytond.convert as convert
|
||||
|
||||
@@ -446,7 +445,6 @@ def load_modules(database_name, pool, update=None, lang=None):
|
||||
Module.update_list()
|
||||
# Need to commit to unlock SQLite database
|
||||
transaction.commit()
|
||||
Cache.resets(database_name)
|
||||
|
||||
if not Transaction().connection:
|
||||
with Transaction().start(database_name, 0):
|
||||
|
||||
@@ -13,7 +13,6 @@ from trytond import backend
|
||||
from trytond.config import config
|
||||
from trytond import __version__
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.exceptions import (
|
||||
UserError, UserWarning, ConcurrencyException, LoginException,
|
||||
RateLimitException)
|
||||
@@ -57,9 +56,6 @@ def login(request, database_name, user, parameters, language=None):
|
||||
except RateLimitException:
|
||||
session = None
|
||||
code = 429
|
||||
with Transaction().start(database_name, 0):
|
||||
Cache.clean(database_name)
|
||||
Cache.resets(database_name)
|
||||
msg = 'successful login' if session else 'bad login or password'
|
||||
logger.info('%s \'%s\' from %s using %s on database \'%s\'',
|
||||
msg, user, request.remote_addr, request.scheme, database_name)
|
||||
@@ -156,7 +152,6 @@ def _dispatch(request, pool, *args, **kwargs):
|
||||
for count in range(config.getint('database', 'retry'), -1, -1):
|
||||
with Transaction().start(pool.database_name, user,
|
||||
readonly=rpc.readonly) as transaction:
|
||||
Cache.clean(pool.database_name)
|
||||
try:
|
||||
c_args, c_kwargs, transaction.context, transaction.timestamp \
|
||||
= rpc.convert(obj, *args, **kwargs)
|
||||
@@ -187,7 +182,6 @@ def _dispatch(request, pool, *args, **kwargs):
|
||||
raise
|
||||
# Need to commit to unlock SQLite database
|
||||
transaction.commit()
|
||||
Cache.resets(pool.database_name)
|
||||
if request.authorization.type == 'session':
|
||||
try:
|
||||
with Transaction().start(pool.database_name, 0) as transaction:
|
||||
|
||||
@@ -16,7 +16,6 @@ from trytond import security, backend
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.config import config
|
||||
from trytond.cache import Cache
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -123,7 +122,6 @@ def with_transaction(readonly=None):
|
||||
pool.database_name, 0, readonly=readonly_
|
||||
) as transaction:
|
||||
try:
|
||||
Cache.clean(pool.database_name)
|
||||
result = func(request, pool, *args, **kwargs)
|
||||
except DatabaseOperationalError:
|
||||
if count and not readonly_:
|
||||
@@ -136,7 +134,6 @@ def with_transaction(readonly=None):
|
||||
raise
|
||||
# Need to commit to unlock SQLite database
|
||||
transaction.commit()
|
||||
Cache.resets(pool.database_name)
|
||||
return result
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
+14
-3
@@ -73,7 +73,7 @@ class Transaction(object):
|
||||
LRUDict(config.getint('cache', 'model')))
|
||||
|
||||
def start(self, database_name, user, readonly=False, context=None,
|
||||
close=False, autocommit=False):
|
||||
close=False, autocommit=False, _nocache=False):
|
||||
'''
|
||||
Start transaction
|
||||
'''
|
||||
@@ -100,6 +100,10 @@ class Transaction(object):
|
||||
self.timestamp = {}
|
||||
self.counter = 0
|
||||
self._datamanagers = []
|
||||
self._nocache = _nocache
|
||||
if not _nocache:
|
||||
from trytond.cache import Cache
|
||||
Cache.clean(database.name)
|
||||
return self
|
||||
|
||||
def __enter__(self):
|
||||
@@ -170,11 +174,12 @@ class Transaction(object):
|
||||
self._local.transactions.append(transaction)
|
||||
return transaction
|
||||
|
||||
def new_transaction(self, autocommit=False, readonly=False):
|
||||
def new_transaction(self, autocommit=False, readonly=False,
|
||||
_nocache=False):
|
||||
transaction = Transaction(new=True)
|
||||
return transaction.start(self.database.name, self.user,
|
||||
context=self.context, close=self.close, readonly=readonly,
|
||||
autocommit=autocommit)
|
||||
autocommit=autocommit, _nocache=_nocache)
|
||||
|
||||
def commit(self):
|
||||
try:
|
||||
@@ -197,6 +202,9 @@ class Transaction(object):
|
||||
logger.critical('A datamanager raised an exception in'
|
||||
' tpc_finish, the data might be inconsistant',
|
||||
exc_info=True)
|
||||
if not self._nocache:
|
||||
from trytond.cache import Cache
|
||||
Cache.resets(self.database.name)
|
||||
|
||||
def rollback(self):
|
||||
for cache in self.cache.itervalues():
|
||||
@@ -204,6 +212,9 @@ class Transaction(object):
|
||||
for datamanager in self._datamanagers:
|
||||
datamanager.tpc_abort(self)
|
||||
self.connection.rollback()
|
||||
if not self._nocache:
|
||||
from trytond.cache import Cache
|
||||
Cache.resets(self.database.name)
|
||||
|
||||
def join(self, datamanager):
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user