forked from OCA/server-tools
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1615 from OCA/17.0
Syncing from upstream OCA/server-tools (17.0)
- Loading branch information
Showing
17 changed files
with
826 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
==================== | ||
Store sessions in DB | ||
==================== | ||
|
||
.. | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! source digest: sha256:7f625ad3c63b7ad41974310cc447302e517eb7fe62290a60ceec8f0325b80853 | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
:target: https://odoo-community.org/page/development-status | ||
:alt: Beta | ||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png | ||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html | ||
:alt: License: LGPL-3 | ||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github | ||
:target: https://github.com/OCA/server-tools/tree/17.0/session_db | ||
:alt: OCA/server-tools | ||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png | ||
:target: https://translation.odoo-community.org/projects/server-tools-17-0/server-tools-17-0-session_db | ||
:alt: Translate me on Weblate | ||
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png | ||
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-tools&target_branch=17.0 | ||
:alt: Try me on Runboat | ||
|
||
|badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
||
Store sessions in a database instead of the filesystem. This simplifies | ||
the configuration of horizontally scalable deployments, by avoiding the | ||
need for a distributed filesystem to store the Odoo sessions. | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Usage | ||
===== | ||
|
||
Set this module in the server wide modules. | ||
|
||
Set a ``SESSION_DB_URI`` environment variable as a full postgresql | ||
connection string, like ``postgres://user:passwd@server/db`` or ``db``. | ||
|
||
It is recommended to use a dedicated database for this module, and | ||
possibly a dedicated postgres user for additional security. | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_. | ||
In case of trouble, please check there if your issue has already been reported. | ||
If you spotted it first, help us to smash it by providing a detailed and welcomed | ||
`feedback <https://github.com/OCA/server-tools/issues/new?body=module:%20session_db%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
||
Do not contact contributors directly about support or help with technical issues. | ||
|
||
Credits | ||
======= | ||
|
||
Authors | ||
------- | ||
|
||
* Odoo SA | ||
* ACSONE SA/NV | ||
|
||
Maintainers | ||
----------- | ||
|
||
This module is maintained by the OCA. | ||
|
||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
mission is to support the collaborative development of Odoo features and | ||
promote its widespread use. | ||
|
||
.. |maintainer-sbidoul| image:: https://github.com/sbidoul.png?size=40px | ||
:target: https://github.com/sbidoul | ||
:alt: sbidoul | ||
|
||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__: | ||
|
||
|maintainer-sbidoul| | ||
|
||
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/17.0/session_db>`_ project on GitHub. | ||
|
||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import pg_session_store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "Store sessions in DB", | ||
"version": "17.0.1.0.0", | ||
"author": "Odoo SA,ACSONE SA/NV,Odoo Community Association (OCA)", | ||
"license": "LGPL-3", | ||
"website": "https://github.com/OCA/server-tools", | ||
"maintainers": ["sbidoul"], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 17.0\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"Last-Translator: \n" | ||
"Language-Team: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: \n" | ||
"Plural-Forms: \n" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
# Copyright (c) Odoo SA 2017 | ||
# @author Nicolas Seinlet | ||
# Copyright (c) ACSONE SA 2022 | ||
# @author Stéphane Bidoul | ||
import json | ||
import logging | ||
import os | ||
|
||
import psycopg2 | ||
|
||
import odoo | ||
from odoo import http | ||
from odoo.tools._vendor import sessions | ||
from odoo.tools.func import lazy_property | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
lock = None | ||
if odoo.evented: | ||
import gevent.lock | ||
|
||
lock = gevent.lock.RLock() | ||
elif odoo.tools.config["workers"] == 0: | ||
import threading | ||
|
||
lock = threading.RLock() | ||
|
||
|
||
def with_lock(func): | ||
def wrapper(*args, **kwargs): | ||
try: | ||
if lock is not None: | ||
lock.acquire() | ||
return func(*args, **kwargs) | ||
finally: | ||
if lock is not None: | ||
lock.release() | ||
|
||
return wrapper | ||
|
||
|
||
def with_cursor(func): | ||
def wrapper(self, *args, **kwargs): | ||
tries = 0 | ||
while True: | ||
tries += 1 | ||
try: | ||
self._ensure_connection() | ||
return func(self, *args, **kwargs) | ||
except (psycopg2.InterfaceError, psycopg2.OperationalError): | ||
self._close_connection() | ||
if tries > 4: | ||
_logger.warning( | ||
"session_db operation try %s/5 failed, aborting", tries | ||
) | ||
raise | ||
_logger.info("session_db operation try %s/5 failed, retrying", tries) | ||
|
||
return wrapper | ||
|
||
|
||
class PGSessionStore(sessions.SessionStore): | ||
def __init__(self, uri, session_class=None): | ||
super().__init__(session_class) | ||
self._uri = uri | ||
self._cr = None | ||
self._open_connection() | ||
self._setup_db() | ||
|
||
def __del__(self): | ||
self._close_connection() | ||
|
||
@with_lock | ||
def _ensure_connection(self): | ||
if self._cr is None: | ||
self._open_connection() | ||
|
||
@with_lock | ||
def _open_connection(self): | ||
self._close_connection() | ||
cnx = odoo.sql_db.db_connect(self._uri, allow_uri=True) | ||
self._cr = cnx.cursor() | ||
self._cr._cnx.autocommit = True | ||
|
||
@with_lock | ||
def _close_connection(self): | ||
"""Return cursor to the pool.""" | ||
if self._cr is not None: | ||
try: | ||
self._cr.close() | ||
except Exception: # pylint: disable=except-pass | ||
pass | ||
self._cr = None | ||
|
||
@with_lock | ||
@with_cursor | ||
def _setup_db(self): | ||
self._cr.execute( | ||
""" | ||
CREATE TABLE IF NOT EXISTS http_sessions ( | ||
sid varchar PRIMARY KEY, | ||
write_date timestamp without time zone NOT NULL, | ||
payload text NOT NULL | ||
) | ||
""" | ||
) | ||
|
||
@with_lock | ||
@with_cursor | ||
def save(self, session): | ||
payload = json.dumps(dict(session)) | ||
self._cr.execute( | ||
""" | ||
INSERT INTO http_sessions(sid, write_date, payload) | ||
VALUES (%(sid)s, now() at time zone 'UTC', %(payload)s) | ||
ON CONFLICT (sid) | ||
DO UPDATE SET payload = %(payload)s, | ||
write_date = now() at time zone 'UTC' | ||
""", | ||
dict(sid=session.sid, payload=payload), | ||
) | ||
|
||
@with_lock | ||
@with_cursor | ||
def delete(self, session): | ||
self._cr.execute("DELETE FROM http_sessions WHERE sid=%s", (session.sid,)) | ||
|
||
@with_lock | ||
@with_cursor | ||
def get(self, sid): | ||
self._cr.execute("SELECT payload FROM http_sessions WHERE sid=%s", (sid,)) | ||
try: | ||
data = json.loads(self._cr.fetchone()[0]) | ||
except Exception: | ||
return self.new() | ||
|
||
return self.session_class(data, sid, False) | ||
|
||
# This method is not part of the Session interface but is called nevertheless, | ||
# so let's get it from FilesystemSessionStore. | ||
rotate = http.FilesystemSessionStore.rotate | ||
|
||
@with_lock | ||
@with_cursor | ||
def vacuum(self, max_lifetime=http.SESSION_LIFETIME): | ||
self._cr.execute( | ||
"DELETE FROM http_sessions " | ||
"WHERE now() at time zone 'UTC' - write_date > %s", | ||
(f"{max_lifetime} seconds",), | ||
) | ||
|
||
|
||
_original_session_store = http.root.__class__.session_store | ||
|
||
|
||
@lazy_property | ||
def session_store(self): | ||
session_db_uri = os.environ.get("SESSION_DB_URI") | ||
if session_db_uri: | ||
_logger.debug("HTTP sessions stored in: db") | ||
return PGSessionStore(session_db_uri, session_class=http.Session) | ||
return _original_session_store.__get__(self, self.__class__) | ||
|
||
|
||
# Monkey patch of standard methods | ||
_logger.debug("Monkey patching session store") | ||
http.root.__class__.session_store = session_store | ||
# Reset the lazy property cache | ||
vars(http.root).pop("session_store", None) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[build-system] | ||
requires = ["whool"] | ||
build-backend = "whool.buildapi" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Store sessions in a database instead of the filesystem. This simplifies | ||
the configuration of horizontally scalable deployments, by avoiding the | ||
need for a distributed filesystem to store the Odoo sessions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Set this module in the server wide modules. | ||
|
||
Set a `SESSION_DB_URI` environment variable as a full postgresql | ||
connection string, like `postgres://user:passwd@server/db` or `db`. | ||
|
||
It is recommended to use a dedicated database for this module, and | ||
possibly a dedicated postgres user for additional security. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.