[FIX] tools.sql, website_*: increment counter with skip lock
*blog, forum, slides Based on https://github.com/odoo/odoo/pull/48552#discussion_r440061218 suggestion Add a new method 'increment_skip_lock' in tools.sql to allow to easily increment a specific field of 1 if the record is not locked. The method return boolean if at least 1 record has been incremented. closes odoo/odoo#58765 X-original-commit: d92e61e89f468c2db2fbd68b2f0d6b36c77f1065 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
@@ -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/<int:blog_id>/post/new', type='http', auth="user", website=True)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 """
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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([{
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user