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.

62 lines
2.3 KiB

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