You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

63 lines
2.3 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2017 Eficent Business and IT Consulting Services S.L.
  3. # (http://www.eficent.com)
  4. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  5. import logging
  6. from odoo import sql_db
  7. from odoo import api, fields, models, _
  8. from odoo.exceptions import ValidationError
  9. _logger = logging.getLogger(__name__)
  10. class IrCron(models.Model):
  11. _inherit = "ir.cron"
  12. @api.one
  13. @api.constrains('mutually_exclusive_cron_ids')
  14. def _check_auto_exclusion(self):
  15. if self in self.mutually_exclusive_cron_ids:
  16. raise ValidationError(_(
  17. "You can not mutually exclude a scheduled actions with "
  18. "itself."))
  19. mutually_exclusive_cron_ids = fields.Many2many(
  20. comodel_name="ir.cron", relation="ir_cron_exclusion",
  21. column1="ir_cron1_id", column2="ir_cron2_id",
  22. string="Mutually Exclusive Scheduled Actions")
  23. @staticmethod
  24. def _lock_mutually_exclusive_cron(db, job_id):
  25. lock_cr = db.cursor()
  26. lock_cr.execute("""
  27. WITH Q1 AS (SELECT ir_cron2_id as cron_id FROM ir_cron_exclusion
  28. WHERE ir_cron1_id=%s
  29. UNION ALL
  30. SELECT ir_cron1_id as cron_id FROM ir_cron_exclusion
  31. WHERE ir_cron2_id=%s)
  32. SELECT * FROM Q1
  33. GROUP BY cron_id;""", (job_id, job_id))
  34. locked_ids = tuple([row[0] for row in lock_cr.fetchall()])
  35. if locked_ids:
  36. lock_cr.execute("""SELECT *
  37. FROM ir_cron
  38. WHERE numbercall != 0
  39. AND active
  40. AND id IN %s
  41. FOR UPDATE NOWAIT""",
  42. (locked_ids,), log_exceptions=False)
  43. lock_cr.fetchall()
  44. return lock_cr
  45. @classmethod
  46. def _process_job(cls, job_cr, job, cron_cr):
  47. db = sql_db.db_connect(cls.pool._db.dbname)
  48. locked_crons = cls._lock_mutually_exclusive_cron(db, job['id'])
  49. try:
  50. res = super(IrCron, cls)._process_job(job_cr, job, cron_cr)
  51. finally:
  52. locked_crons.close()
  53. _logger.debug("released blocks for cron job %s" % job['name'])
  54. return res