/tipper/__init__.py

https://github.com/AnimeDB/adb-browser-backend
Python | 98 lines | 71 code | 25 blank | 2 comment | 6 complexity | 558ff68fae5ee16a1f8230fc58b39421 MD5 | raw file
  1. import json
  2. import time
  3. import MySQLdb as db
  4. from twisted.application.service import Service
  5. from twisted.internet import task, threads, defer, reactor
  6. from twisted.python import log
  7. from txamqp.client import TwistedDelegate
  8. from backend.amqp import get_spec
  9. from tipper.publisher import PublisherFactory
  10. from tipper.installer import install
  11. class Poller(Service, object):
  12. def __init__(self, options, config):
  13. super(Poller, self).__init__()
  14. self.options = options
  15. self.config = config
  16. self.polling_call = None
  17. self.sql_connection = None
  18. self.publisher_factory = None
  19. def privilegedStartService(self):
  20. if self.options['install']:
  21. install(self.config)
  22. @defer.inlineCallbacks
  23. def startService(self):
  24. super(Poller, self).startService()
  25. queue = defer.DeferredQueue()
  26. # Init AMQP connection
  27. kwargs = {
  28. 'config': self.config,
  29. 'queue': queue,
  30. 'delegate': TwistedDelegate(),
  31. 'vhost': self.config.get('amqp', 'vhost'),
  32. 'spec': get_spec(),
  33. }
  34. self.publisher_factory = PublisherFactory(**kwargs)
  35. reactor.connectTCP(
  36. self.config.get('amqp', 'host'),
  37. int(self.config.get('amqp', 'port')),
  38. self.publisher_factory
  39. )
  40. # Init MySQL connection
  41. kwargs = {
  42. 'host': self.config.get('database', 'host'),
  43. 'port': int(self.config.get('database', 'port')),
  44. 'user': self.config.get('database', 'user'),
  45. 'passwd': self.config.get('database', 'password'),
  46. 'db': self.config.get('database', 'temp'),
  47. 'use_unicode': True
  48. }
  49. self.sql_connection = yield threads.deferToThread(db.connect, **kwargs)
  50. def poll(cursor, query, rate):
  51. cursor.execute(query, (rate,))
  52. for row in cursor.fetchall():
  53. row = json.dumps(row)
  54. threads.blockingCallFromThread(reactor, queue.put, row)
  55. self.polling_call = task.LoopingCall(
  56. threads.deferToThread,
  57. poll,
  58. self.sql_connection.cursor(),
  59. "SELECT * FROM post_updates ORDER BY timestamp ASC LIMIT 0,%d",
  60. int(self.config.get('polling', 'rate'))
  61. )
  62. self.polling_call.start(int(self.config.get('polling', 'interval')))
  63. @defer.inlineCallbacks
  64. def stopService(self):
  65. super(Poller, self).stopService()
  66. if self.publisher_factory:
  67. self.publisher_factory.stopTrying()
  68. if self.polling_call and self.polling_call.running:
  69. self.polling_call.stop()
  70. log.msg("Waiting for all SQL requests to terminate...")
  71. yield threads.deferToThread(time.sleep, 2)
  72. if self.sql_connection:
  73. yield threads.deferToThread(self.sql_connection.close)