summaryrefslogtreecommitdiff
path: root/addons/bus/models/bus_presence.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/bus/models/bus_presence.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/bus/models/bus_presence.py')
-rw-r--r--addons/bus/models/bus_presence.py71
1 files changed, 71 insertions, 0 deletions
diff --git a/addons/bus/models/bus_presence.py b/addons/bus/models/bus_presence.py
new file mode 100644
index 00000000..2f6545bc
--- /dev/null
+++ b/addons/bus/models/bus_presence.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+import datetime
+import time
+
+from psycopg2 import OperationalError
+
+from odoo import api, fields, models
+from odoo import tools
+from odoo.addons.bus.models.bus import TIMEOUT
+from odoo.service.model import PG_CONCURRENCY_ERRORS_TO_RETRY
+from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
+
+DISCONNECTION_TIMER = TIMEOUT + 5
+AWAY_TIMER = 1800 # 30 minutes
+
+
+class BusPresence(models.Model):
+ """ User Presence
+ Its status is 'online', 'away' or 'offline'. This model should be a one2one, but is not
+ attached to res_users to avoid database concurrence errors. Since the 'update' method is executed
+ at each poll, if the user have multiple opened tabs, concurrence errors can happend, but are 'muted-logged'.
+ """
+
+ _name = 'bus.presence'
+ _description = 'User Presence'
+ _log_access = False
+
+ _sql_constraints = [('bus_user_presence_unique', 'unique(user_id)', 'A user can only have one IM status.')]
+
+ user_id = fields.Many2one('res.users', 'Users', required=True, index=True, ondelete='cascade')
+ last_poll = fields.Datetime('Last Poll', default=lambda self: fields.Datetime.now())
+ last_presence = fields.Datetime('Last Presence', default=lambda self: fields.Datetime.now())
+ status = fields.Selection([('online', 'Online'), ('away', 'Away'), ('offline', 'Offline')], 'IM Status', default='offline')
+
+ @api.model
+ def update(self, inactivity_period):
+ """ Updates the last_poll and last_presence of the current user
+ :param inactivity_period: duration in milliseconds
+ """
+ # This method is called in method _poll() and cursor is closed right
+ # after; see bus/controllers/main.py.
+ try:
+ self._update(inactivity_period)
+ # commit on success
+ self.env.cr.commit()
+ except OperationalError as e:
+ if e.pgcode in PG_CONCURRENCY_ERRORS_TO_RETRY:
+ # ignore concurrency error
+ return self.env.cr.rollback()
+ raise
+
+ @api.model
+ def _update(self, inactivity_period):
+ presence = self.search([('user_id', '=', self._uid)], limit=1)
+ # compute last_presence timestamp
+ last_presence = datetime.datetime.now() - datetime.timedelta(milliseconds=inactivity_period)
+ values = {
+ 'last_poll': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ }
+ # update the presence or a create a new one
+ if not presence: # create a new presence for the user
+ values['user_id'] = self._uid
+ values['last_presence'] = last_presence
+ self.create(values)
+ else: # update the last_presence if necessary, and write values
+ if presence.last_presence < last_presence:
+ values['last_presence'] = last_presence
+ # Hide transaction serialization errors, which can be ignored, the presence update is not essential
+ with tools.mute_logger('odoo.sql_db'):
+ presence.write(values)
+ presence.flush()