If there are too many schedulers running on a single instance, it leads to lot of concurrent update error. In order to speed up the process and minimize concurrent update error, we can do the following

  1. Assign different user to each schedulers. Make sure this user have sufficient rights to run the function.
  2. We can make schedulers run on different instance. For eg., we can set up different instances 8069, 8169, 8269 and so on. Next we can group schedulers based on their functionality and run it on separate instance.

Now, how do we make sure that an instance runs only on the configured instance. For eg., if I have 3 schedulers A, B and C which should  run on 8069, 8169 and 8269 respectively. In order to achieve this, we need to do the following

    • Add a new field- port_no in ir.cron class- 'port_no': fields.char('Port Number', size=4). Make sure this field is visible in view where user can configure the desired port.
    • Modify _run_job() to check if the scheduler is getting called on right instance.
       
      def _check_execute_cron(self, cr, uid, job):
          port_no = job.get('port_no',False)
          xmlrpc_port = tools.config.options['xmlrpc_port']
          execute_cron = True
          if port_no and xmlrpc_port:
              execute_cron = False
              if int(port_no) == int(xmlrpc_port):
                  execute_cron = True
          return execute_cron
      
      def _run_job(self, cr, job, now):
      """
      Inherited to check if the cron is running on specified port
      """
          try:
              execute_cron = self._check_execute_cron(cr, job['user_id'], job)
              if execute_cron:
                  nextcall = datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT)
                  numbercall = job['numbercall']
      
                  ok = False
                  while nextcall < now and numbercall:
                      if numbercall > 0:
                          numbercall -= 1
                      if not ok or job['doall']:
                          self._callback(cr, job['user_id'], job['model'], job['function'], job['args'], job['id'])
                       nextcall += _intervalTypes[job['interval_type']](job['interval_number'])
                       ok = True
                  addsql = ''
                  if not numbercall:
                       addsql = ', active=False'
                  cr.execute("UPDATE ir_cron SET nextcall=%s, numbercall=%s"+addsql+" WHERE id=%s",
                              (nextcall.strftime(DEFAULT_SERVER_DATETIME_FORMAT), numbercall, job['id']))
      
                  if numbercall:
                     # Reschedule our own main cron thread if necessary.
                     # This is really needed if this job runs longer than its rescheduling period.
                     nextcall = calendar.timegm(nextcall.timetuple())
                     openerp.cron.schedule_wakeup(nextcall, cr.dbname)
          finally:
             cr.commit()
             cr.close()
             openerp.cron.release_thread_slot()
Advertisements