cron_task.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/env python2
  2. import signal
  3. import traceback
  4. from sys import stderr
  5. from datetime import datetime, timedelta
  6. from flask.ext.mail import Message
  7. from flask import url_for
  8. from ffdnispdb.crawler import TextValidator
  9. from ffdnispdb.models import ISP
  10. from ffdnispdb import app, db, mail
  11. MAX_RUNTIME=15*60
  12. class Timeout(Exception):
  13. pass
  14. class ScriptTimeout(Exception):
  15. """
  16. Script exceeded its allowed run time
  17. """
  18. strike=1
  19. last_isp=-1
  20. script_begin=datetime.now()
  21. def timeout_handler(signum, frame):
  22. global last_isp, strike
  23. if script_begin < datetime.now()-timedelta(seconds=MAX_RUNTIME):
  24. raise ScriptTimeout
  25. if last_isp == isp.id:
  26. strike += 1
  27. if strike > 2:
  28. signal.alarm(6)
  29. raise Timeout
  30. else:
  31. last_isp = isp.id
  32. strike = 1
  33. signal.alarm(6)
  34. signal.signal(signal.SIGALRM, timeout_handler)
  35. signal.alarm(6)
  36. def send_warning_email(isp, debug_msg):
  37. msg=Message(u"Problem while updating your ISP's data", sender=('FFDN DB <cron@db.ffdn.org>'))
  38. msg.body = """
  39. Hello,
  40. You are receiving this mail because your ISP, %s, is registered on the FFDN ISP Database.
  41. Our automatic update script could not access or process your ISP's data located at %s.
  42. Automatic updates of your ISP were disabled until you fix the problem.
  43. Here is some debug output to help you locate the issue:
  44. %s
  45. ---
  46. When the issue is resolved, please click on the link below to reactivate automatic updates on your ISP:
  47. %s
  48. Thanks,
  49. The FFDN ISP Database team
  50. """.strip()%(isp.complete_name, isp.json_url, debug_msg.strip(), url_for('home'))
  51. msg.add_recipient(isp.tech_email)
  52. mail.send(msg)
  53. app.config['SERVER_NAME'] = 'db.ffdn.org'
  54. app.app_context().push()
  55. try:
  56. for isp in ISP.query.filter(ISP.is_disabled == False,
  57. ISP.json_url != None,
  58. ISP.next_update < datetime.now(),
  59. ISP.update_error_strike < 3)\
  60. .order_by(ISP.last_update_success):
  61. try:
  62. print u'%s: Attempting to update %s'%(datetime.now(), isp)
  63. print u' last successful update=%s'%(isp.last_update_success)
  64. print u' last update attempt=%s'%(isp.last_update_attempt)
  65. print u' next update was scheduled %s ago'%(datetime.now()-isp.next_update)
  66. print u' strike=%d'%(isp.update_error_strike)
  67. isp.last_update_attempt=datetime.now()
  68. db.session.add(isp)
  69. db.session.commit()
  70. validator=TextValidator()
  71. log=''.join(validator(isp.json_url, isp.cache_info or {}))
  72. if not validator.success: # handle error
  73. isp.update_error_strike += 1
  74. if isp.cache_info:
  75. isp.cache_info = validator.cache_info
  76. isp.next_update = datetime.now()+timedelta(seconds=validator.jdict_max_age)
  77. db.session.add(isp)
  78. db.session.commit()
  79. print u'%s: Error while updating:'%(datetime.now())
  80. if isp.update_error_strike >= 3:
  81. send_warning_email(isp, log)
  82. print u' three strikes, you\'re out'
  83. print log.rstrip()+'\n'
  84. continue
  85. if validator.modified:
  86. isp.json = validator.jdict
  87. isp.cache_info = validator.cache_info
  88. isp.last_update_success = isp.last_update_attempt
  89. isp.update_error_strike = 0
  90. isp.next_update = datetime.now()+timedelta(seconds=validator.jdict_max_age)
  91. db.session.add(isp)
  92. db.session.commit()
  93. print u'%s: Update successful !'%(datetime.now())
  94. print u' next update is scheduled for %s\n'%(isp.next_update)
  95. except Timeout:
  96. print u'%s: Timeout while updating:'%(datetime.now())
  97. isp=ISP.query.get(isp.id)
  98. isp.update_error_strike += 1
  99. db.session.add(isp)
  100. db.session.commit()
  101. if isp.update_error_strike >= 3:
  102. send_warning_email(isp, 'Your ISP took more then 18 seconds to process. '
  103. 'Having problems with your webserver ?')
  104. print u' three strikes, you\'re out'
  105. print traceback.format_exc()
  106. except ScriptTimeout:
  107. pass
  108. except Timeout:
  109. pass