Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

180 řádky
4.3 KiB

  1. """
  2. Simple Scheduler
  3. This scheduler is used to fire events across multiple databases. A database
  4. master_scheduler is maintained with one event and one log table
  5. Events are added by different databases in the master scheduler using the
  6. `set_event` method and they are executed by the cron.
  7. __main__ will call run
  8. To install:
  9. -----------
  10. python install_lib.py [root] [password] master_scheduler
  11. In cron:
  12. --------
  13. python [path]webnotes/utils/scheduler.py
  14. """
  15. class Scheduler:
  16. def connect(self):
  17. """
  18. Connect to the 'master_schduler' database
  19. """
  20. if hasattr(self,'conn'): return
  21. import webnotes.defs, webnotes.db
  22. pwd = webnotes.defs.__dict__.get('scheduler_password')
  23. if pwd==None: pwd = webnotes.defs.db_password
  24. self.conn = webnotes.db.Database(user='master_scheduler',password=pwd)
  25. def set(self, event, interval, recurring, db_name=None):
  26. """
  27. Add an event to the Event table in the master scheduler
  28. """
  29. self.connect()
  30. if not db_name:
  31. import webnotes
  32. db_name = webnotes.conn.cur_db_name
  33. self.clear(db_name, event)
  34. self.conn.sql("""insert into
  35. Event (`db_name`, `event`, `interval`, next_execution, recurring)
  36. values (%s, %s, %s, ADDTIME(NOW(), SEC_TO_TIME(%s)), %s)
  37. """, (webnotes.conn.cur_db_name, event, interval, interval, recurring))
  38. def get_events(self, db_name=None):
  39. """
  40. Returns list of upcoming events
  41. """
  42. self.connect()
  43. if not db_name:
  44. import webnotes
  45. db_name = webnotes.conn.cur_db_name
  46. return self.conn.sql("select * from Event where db_name=%s", db_name, as_dict=1)
  47. def get_log(self, db_name=None):
  48. """
  49. Returns log of events
  50. """
  51. self.connect()
  52. if not db_name:
  53. import webnotes
  54. db_name = webnotes.conn.cur_db_name
  55. return self.conn.sql("select * from EventLog where db_name=%s limit 50", db_name, as_dict=1)
  56. def clear(self, db_name, event):
  57. """
  58. Clears the event
  59. """
  60. self.connect()
  61. self.conn.sql("delete from Event where `event`=%s and db_name=%s", (event, db_name))
  62. def execute(self, db_name, event, now):
  63. """
  64. Executes event in the specifed db
  65. """
  66. import webnotes, webnotes.defs, webnotes.db
  67. try:
  68. webnotes.conn = webnotes.db.Database(user=db_name, password=webnotes.get_db_password(db_name))
  69. webnotes.session = {'user':'Administrator'}
  70. module = '.'.join(event.split('.')[:-1])
  71. method = event.split('.')[-1]
  72. exec 'from %s import %s' % (module, method)
  73. webnotes.conn.begin()
  74. ret = locals()[method]()
  75. webnotes.conn.commit()
  76. webnotes.conn.close()
  77. self.log(db_name, event, ret or 'Ok')
  78. except Exception, e:
  79. if now:
  80. print webnotes.getTraceback()
  81. else:
  82. self.log(db_name, event, webnotes.getTraceback())
  83. def log(self, db_name, event, traceback):
  84. """
  85. Log an event error
  86. """
  87. self.conn.sql("insert into `EventLog`(db_name, event, log, executed_on) values (%s, %s, %s, now())", \
  88. (db_name, event, traceback))
  89. # delete old logs
  90. self.conn.sql("delete from EventLog where executed_on < subdate(curdate(), interval 30 day)")
  91. def run(self, now=0):
  92. """
  93. Run scheduled (due) events and reset time for recurring events
  94. """
  95. cond = ''
  96. if not now:
  97. cond = 'where next_execution < NOW()'
  98. el = self.conn.sql("""select `db_name`, `event`, `recurring`, `interval`
  99. from `Event`
  100. %s""" % cond, as_dict=1)
  101. for e in el:
  102. # execute the event
  103. self.execute(e['db_name'], e['event'], now)
  104. # if recurring, update next_execution
  105. if e['recurring']:
  106. self.conn.sql("update Event set next_execution = addtime(now(), sec_to_time(%s)) where event=%s", (e['interval'], e['event']))
  107. # else clear
  108. else:
  109. self.clear(e['db_name'], e['event'])
  110. def set_event(event, interval=60*60*24, recurring=1):
  111. """
  112. Adds an event to the master scheduler
  113. """
  114. return Scheduler().set(event, interval, recurring)
  115. def cancel_event(event):
  116. """
  117. Cancels an event
  118. """
  119. import webnotes
  120. return Scheduler().clear(webnotes.conn.cur_db_name, event)
  121. # to be called from cron
  122. if __name__=='__main__':
  123. import os,sys
  124. cgi_bin_path = os.path.sep.join(os.path.abspath(__file__).split(os.path.sep)[:-3])
  125. sys.path.append(cgi_bin_path)
  126. import webnotes
  127. import webnotes.defs
  128. sys.path.append(getattr(webnotes.defs,'modules_path',None))
  129. sch = Scheduler()
  130. sch.connect()
  131. if len(sys.argv) > 1 and sys.argv[1]=='run':
  132. sch.run(now=1)
  133. else:
  134. sch.run()