1. 程式人生 > >odoo 定時任務的使用方法

odoo 定時任務的使用方法

編寫執行程式

編寫openerp模組程式碼,在模組程式碼中編寫執行程式! 此處為了方便,只是做了簡單的列印輸入, 程式碼如下:

# -*- coding: utf-8 -*-
from openerp.osv import osv

class task_test(osv.osv):
    _auto = False
    _name = "task.test"

    def run_scheduler(self, cr, uid, args,context=None):
        print "test scheduler"

配置任務執行引數

在模組中申明一個xxx_data.xml

檔案,xxx可以不為模組名稱,然後在openerp.py 檔案中的data屬性中加入xxx_data.xml即可,xxx_data.xml檔案的配置內容如下:

<?xml version="1.0" encoding="utf-8"?>
<openerp>
    <data noupdate="1">
        <record forcecreate="True" id="ir_cron_scheduler_action" model="ir.cron">
            <field name="name">
Run mrp scheduler</field> <field eval="True" name="active"/> <field name="user_id" ref="base.user_root"/> <field name="interval_number">1</field> <field name="interval_type">minutes</field> <field name
="numbercall">
3</field> <field eval="False" name="doall"/> <field eval="'task.test'" name="model"/> <field eval="'run_scheduler'" name="function"/> <field eval="'(True,)'" name="args"/> </record> </data> </openerp>

配置引數說明

從上面我們可以看到配置的這個xxx_data.xml檔案在檔案的第4行配置了model="ir.cron" 那麼我們在oe中開啟model ir_cron 可以看到該class的_columns有如下欄位:

_columns = {
        'name': fields.char('Name', required=True),
        'user_id': fields.many2one('res.users', 'User', required=True),
        'active': fields.boolean('Active'),
        'interval_number': fields.integer('Interval Number',help="Repeat every x."),
        'interval_type': fields.selection( [('minutes', 'Minutes'),
            ('hours', 'Hours'), ('work_days','Work Days'), ('days', 'Days'),('weeks', 'Weeks'), ('months', 'Months')], 'Interval Unit'),
        'numbercall': fields.integer('Number of Calls', help='How many times the method is called,\na negative number indicates no limit.'),
        'doall' : fields.boolean('Repeat Missed', help="Specify if missed occurrences should be executed when the server restarts."),
        'nextcall' : fields.datetime('Next Execution Date', required=True, help="Next planned execution date for this job."),
        'model': fields.char('Object', help="Model name on which the method to be called is located, e.g. 'res.partner'."),
        'function': fields.char('Method', help="Name of the method to be called when this job is processed."),
        'args': fields.text('Arguments', help="Arguments to be passed to the method, e.g. (uid,)."),
        'priority': fields.integer('Priority', help='The priority of the job, as an integer: 0 means higher priority, 10 means lower priority.')
    }
  • name 即該task的名稱,由使用者定義為該task主要的職責
  • user_id 對應res_users表,需要一個使用者ID
  • active 是否啟用該task,預設為True
  • interval_number 間隔時間,型別為integer
  • interval_type 執行task的週期型別,只能選擇分鐘、小時、天、周、月,可惜沒有秒。
  • numbercall 方法呼叫多少次,-1則是沒有限制
  • doall 如果任務執行時間錯過了伺服器重啟時間是否重新執行任務
  • nextcall 下次的呼叫時間,我們不用配置,oe會自動計算
  • model 即模組名稱
  • function 要執行的方法
  • args 傳遞的引數
  • priority 任務優先級別 0是最高級別,10是最低級別

執行過程

ir_cron模組中主要有三個主要的方法分別為:_callback_process_job_acquire_job ,在server.py檔案中有如下的Python程式碼:

def cron_thread(self, number):
        while True:
            time.sleep(SLEEP_INTERVAL + number)     # Steve Reich timing style
            registries = openerp.modules.registry.RegistryManager.registries
            _logger.debug('cron%d polling for jobs', number)
            for db_name, registry in registries.items():
                while True and registry.ready:
                    acquired = openerp.addons.base.ir.ir_cron.ir_cron._acquire_job(db_name)
                    if not acquired:
                        break

到此呼叫過程就清楚了,server先呼叫_acquire_job 方法,_acquire_job 會根據dbname獲取任務執行的相關資料、例如獲取資料操作cr物件,要執行的jobs等,例如:

 db = openerp.sql_db.db_connect(db_name)
 threading.current_thread().dbname = db_name
 cr = db.cursor()

,這個程式碼又幫我們瞭解到瞭如何獲取資料庫的cr物件。_acquire_job獲取相關資料之後,然後交給_process_job方法,該方法會去更新任務的下一次執行時間等資料,然後交由_callback 方法,有興趣的可以去讀一下ir_cronserver的原始碼。