diff --git a/addons/website_blog/controllers/main.py b/addons/website_blog/controllers/main.py index 17968fb81a9..2249ab7c5a3 100644 --- a/addons/website_blog/controllers/main.py +++ b/addons/website_blog/controllers/main.py @@ -15,6 +15,7 @@ from odoo.http import request from odoo.osv import expression from odoo.tools import html2plaintext from odoo.tools.misc import get_lang +from odoo.tools import sql class WebsiteBlog(http.Controller): @@ -272,17 +273,11 @@ class WebsiteBlog(http.Controller): response = request.render("website_blog.blog_post_complete", values) if blog_post.id not in request.session.get('posts_viewed', []): - if not request.session.get('posts_viewed'): - request.session['posts_viewed'] = [] - - request.session['posts_viewed'].append(blog_post.id) - request.session.modified = True - - # Increase counter - blog_post.sudo()._write({ - 'visits': blog_post.visits + 1, - 'write_date': blog_post.write_date, - }) + if sql.increment_field_skiplock(blog_post, 'visits'): + if not request.session.get('posts_viewed'): + request.session['posts_viewed'] = [] + request.session['posts_viewed'].append(blog_post.id) + request.session.modified = True return response @http.route('/blog//post/new', type='http', auth="user", website=True) diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py index bf1276ee3bd..3f7865c3525 100644 --- a/addons/website_forum/controllers/main.py +++ b/addons/website_forum/controllers/main.py @@ -260,7 +260,7 @@ class WebsiteForum(WebsiteProfile): values['back_button_url'] = request.httprequest.referrer # increment view counter - question.sudo().set_viewed() + question.sudo()._set_viewed() return request.render("website_forum.post_description_full", values) diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index 1315e3ac7f3..d9c0ce6d058 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -9,7 +9,7 @@ from datetime import datetime from odoo import api, fields, models, tools, SUPERUSER_ID, _ from odoo.exceptions import UserError, ValidationError, AccessError -from odoo.tools import misc +from odoo.tools import misc, sql from odoo.tools.translate import html_translate from odoo.addons.http_routing.models.ir_http import slug @@ -856,10 +856,9 @@ class Post(models.Model): result.append(comment.unlink()) return result - def set_viewed(self): + def _set_viewed(self): self.ensure_one() - self._cr.execute("""UPDATE forum_post SET views = views+1 WHERE views = %s and id = %s""", (self.views, self.id,)) - return True + return sql.increment_field_skiplock(self, 'views') def get_access_action(self, access_uid=None): """ Instead of the classic form view, redirect to the post on the website directly """ diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 916c27869ca..78972fd3565 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -58,9 +58,9 @@ class WebsiteSlides(WebsiteProfile): if request.env.user._is_public() or not slide.website_published or not slide.channel_id.is_member: viewed_slides = request.session.setdefault('viewed_slides', list()) if slide.id not in viewed_slides: - slide.sudo().public_views += 1 - viewed_slides.append(slide.id) - request.session['viewed_slides'] = viewed_slides + if tools.sql.increment_field_skiplock(slide, 'public_views'): + viewed_slides.append(slide.id) + request.session['viewed_slides'] = viewed_slides else: slide.action_set_viewed(quiz_attempts_inc=quiz_attempts_inc) return True diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 7ba3f1d6a31..a5de10dc7fd 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -18,6 +18,7 @@ from odoo.addons.http_routing.models.ir_http import slug from odoo.exceptions import Warning, UserError, AccessError from odoo.http import request from odoo.addons.http_routing.models.ir_http import url_for +from odoo.tools import sql class SlidePartnerRelation(models.Model): @@ -629,11 +630,8 @@ class Slide(models.Model): ('slide_id', 'in', self.ids), ('partner_id', '=', target_partner.id) ]) - if quiz_attempts_inc: - for exsting_slide in existing_sudo: - exsting_slide.write({ - 'quiz_attempts_count': exsting_slide.quiz_attempts_count + 1 - }) + if quiz_attempts_inc and existing_sudo: + sql.increment_field_skiplock(existing_sudo, 'quiz_attempts_count') new_slides = self_sudo - existing_sudo.mapped('slide_id') return SlidePartnerSudo.create([{ diff --git a/odoo/tools/sql.py b/odoo/tools/sql.py index 69968f78de8..fc3d6f5524e 100644 --- a/odoo/tools/sql.py +++ b/odoo/tools/sql.py @@ -253,3 +253,27 @@ def reverse_order(order): direction = 'asc' if item[1:] == ['desc'] else 'desc' items.append('%s %s' % (item[0], direction)) return ', '.join(items) + + +def increment_field_skiplock(record, field): + """ + Increment 'friendly' the [field] of the current [record](s) + If record is locked, we just skip the update. + It doesn't invalidate the cache since the update is not critical. + + :rtype: bool - if field has been incremented or not + """ + if not record: + return False + + assert record._fields[field].type == 'integer' + + cr = record._cr + query = """ + UPDATE {table} SET {field} = {field} + 1 WHERE id IN ( + SELECT id from {table} WHERE id in %(ids)s FOR UPDATE SKIP LOCKED + ) RETURNING id + """.format(table=record._table, field=field) + cr.execute(query, {'ids': tuple(record.ids)}) + + return bool(cr.fetchone())