changeset 32cd371b3e9c in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset;node=32cd371b3e9c
description:
Refresh pool of other processes
When a process change the list of activated modules, the others must
refresh
their pool. We do that by just stopping the pool for that database, the
next
request will load the new pool.
issue8988
review302861002
diffstat:
CHANGELOG | 1 +
trytond/cache.py | 31 ++++++++++++++++++++++++++++++-
trytond/ir/module.py | 5 ++++-
trytond/modules/__init__.py | 1 +
trytond/pool.py | 16 ++++++++++------
5 files changed, 46 insertions(+), 8 deletions(-)
diffs (157 lines):
diff -r 9da9d1618bec -r 32cd371b3e9c CHANGELOG
--- a/CHANGELOG Mon Jan 18 23:20:40 2021 +0100
+++ b/CHANGELOG Wed Jan 20 00:52:07 2021 +0100
@@ -1,3 +1,4 @@
+* Refresh pool of other processes
* Add clear_all method to Cache
* Support Genshi element directives in HTML editor
* Add firstline tool
diff -r 9da9d1618bec -r 32cd371b3e9c trytond/cache.py
--- a/trytond/cache.py Mon Jan 18 23:20:40 2021 +0100
+++ b/trytond/cache.py Wed Jan 20 00:52:07 2021 +0100
@@ -16,6 +16,7 @@
from trytond import backend
from trytond.config import config
+from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.tools import resolve, grouped_slice
@@ -43,6 +44,15 @@
return o
+def _get_modules(cursor):
+ ir_module = Table('ir_module')
+ cursor.execute(*ir_module.select(
+ ir_module.name,
+ where=ir_module.state.in_(
+ ['activated', 'to upgrade', 'to remove'])))
+ return {m for m, in cursor}
+
+
class BaseCache(object):
_instances = {}
@@ -195,6 +205,7 @@
timestamps = {}
for timestamp, name in cursor.fetchall():
timestamps[name] = timestamp
+ modules = _get_modules(cursor)
finally:
database.put_connection(connection)
for name, timestamp in timestamps.items():
@@ -205,6 +216,7 @@
inst_timestamp = inst._timestamp.get(dbname)
if not inst_timestamp or timestamp > inst_timestamp:
inst._clear(dbname, timestamp)
+ Pool(dbname).refresh(modules)
cls._clean_last = datetime.now()
def sync_since(self, value):
@@ -292,6 +304,21 @@
inst._transaction_lower.pop(dbname, None)
@classmethod
+ def refresh_pool(cls, transaction):
+ database = transaction.database
+ dbname = database.name
+ if not _clear_timeout and database.has_channel():
+ database = backend.Database(dbname)
+ conn = database.get_connection()
+ try:
+ cursor = conn.cursor()
+ cursor.execute(
+ 'NOTIFY "%s", %%s' % cls._channel, ('refresh pool',))
+ conn.commit()
+ finally:
+ database.put_connection(conn)
+
+ @classmethod
def _listen(cls, dbname):
database = backend.Database(dbname)
if not database.has_channel():
@@ -313,7 +340,9 @@
conn.poll()
while conn.notifies:
notification = conn.notifies.pop()
- if notification.payload:
+ if notification.payload == 'refresh pool':
+ Pool(dbname).refresh(_get_modules(cursor))
+ elif notification.payload:
reset = json.loads(notification.payload)
for name in reset:
inst = cls._instances[name]
diff -r 9da9d1618bec -r 32cd371b3e9c trytond/ir/module.py
--- a/trytond/ir/module.py Mon Jan 18 23:20:40 2021 +0100
+++ b/trytond/ir/module.py Wed Jan 20 00:52:07 2021 +0100
@@ -5,6 +5,7 @@
from sql.operators import NotIn
+from trytond.cache import Cache
from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.model import ModelView, ModelSQL, fields, Unique, sequence_ordered
@@ -557,7 +558,8 @@
pool = Pool()
Module = pool.get('ir.module')
Lang = pool.get('ir.lang')
- with Transaction().new_transaction():
+ transaction = Transaction()
+ with transaction.new_transaction():
modules = Module.search([
('state', 'in', ['to upgrade', 'to remove', 'to activate']),
])
@@ -568,6 +570,7 @@
lang = [x.code for x in langs]
if update:
pool.init(update=update, lang=lang)
+ Cache.refresh_pool(transaction)
return 'done'
diff -r 9da9d1618bec -r 32cd371b3e9c trytond/modules/__init__.py
--- a/trytond/modules/__init__.py Mon Jan 18 23:20:40 2021 +0100
+++ b/trytond/modules/__init__.py Wed Jan 20 00:52:07 2021 +0100
@@ -302,6 +302,7 @@
# Ensure cache is clear for other instances
Cache.clear_all()
+ Cache.refresh_pool(transaction)
logger.info('all modules loaded')
diff -r 9da9d1618bec -r 32cd371b3e9c trytond/pool.py
--- a/trytond/pool.py Mon Jan 18 23:20:40 2021 +0100
+++ b/trytond/pool.py Wed Jan 20 00:52:07 2021 +0100
@@ -113,12 +113,12 @@
with cls._lock:
if database_name in cls._instances:
del cls._instances[database_name]
- lock = cls._locks.get(database_name)
- if not lock:
- return
- with lock:
- if database_name in cls._pool:
- del cls._pool[database_name]
+ lock = cls._locks.get(database_name)
+ if not lock:
+ return
+ with lock:
+ if database_name in cls._pool:
+ del cls._pool[database_name]
@classmethod
def database_list(cls):
@@ -271,6 +271,10 @@
cls.__name__, (mixin, cls), {'__slots__': ()})
self.add(cls, type=type_)
+ def refresh(self, modules):
+ if set(self._modules) != modules:
+ self.stop(self.database_name)
+
def isregisteredby(obj, module, type_='model'):
pool = Pool()