app.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #!/usr/bin/env python
  2. from functools import partial
  3. import json
  4. from operator import attrgetter
  5. import os
  6. from random import randint
  7. import sys
  8. import flask
  9. from flask import Flask, request, render_template, make_response, jsonify
  10. from flask_sqlalchemy import SQLAlchemy
  11. from sqlalchemy import create_engine
  12. from sqlalchemy.ext import baked
  13. if sys.version_info[0] == 3:
  14. xrange = range
  15. _is_pypy = hasattr(sys, 'pypy_version_info')
  16. DBDRIVER = 'mysql+pymysql' if _is_pypy else 'mysql' # mysqlclient is slow on PyPy
  17. DBHOST = os.environ.get('DBHOST', 'localhost')
  18. # setup
  19. app = Flask(__name__)
  20. app.config['SQLALCHEMY_DATABASE_URI'] = DBDRIVER + '://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world?charset=utf8' % DBHOST
  21. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
  22. app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
  23. db = SQLAlchemy(app)
  24. dbraw_engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'], connect_args={'autocommit': True}, pool_reset_on_return=None)
  25. bakery = baked.bakery()
  26. # models
  27. class World(db.Model):
  28. __tablename__ = "world"
  29. id = db.Column(db.Integer, primary_key=True)
  30. randomNumber = db.Column(db.Integer)
  31. # http://stackoverflow.com/questions/7102754/jsonify-a-sqlalchemy-result-set-in-flask
  32. @property
  33. def serialize(self):
  34. """Return object data in easily serializeable format"""
  35. return {
  36. 'id' : self.id,
  37. 'randomNumber': self.randomNumber
  38. }
  39. @staticmethod
  40. def get(ident):
  41. baked_query = bakery(lambda s: s.query(World))
  42. return baked_query(db.session()).get(ident)
  43. class Fortune(db.Model):
  44. __tablename__ = "fortune"
  45. id = db.Column(db.Integer, primary_key=True)
  46. message = db.Column(db.String)
  47. # views
  48. # flask.jsonify doesn't allow array at top level for security concern.
  49. # So we should have oriiginal one.
  50. def json_response(obj):
  51. res = make_response(json.dumps(obj))
  52. res.mimetype = "application/json"
  53. return res
  54. @app.route("/json")
  55. def hello():
  56. return jsonify(message='Hello, World!')
  57. @app.route("/db")
  58. def get_random_world():
  59. num_queries = request.args.get("queries", 1, type=int)
  60. if num_queries < 1:
  61. num_queries = 1
  62. if num_queries > 500:
  63. num_queries = 500
  64. worlds = [World.get(randint(1, 10000)).serialize
  65. for _ in xrange(num_queries)]
  66. return json_response(worlds)
  67. @app.route("/dbs")
  68. def get_random_world_single():
  69. wid = randint(1, 10000)
  70. worlds = World.get(wid).serialize
  71. return json_response(worlds)
  72. @app.route("/dbraw")
  73. def get_random_world_raw():
  74. connection = dbraw_engine.connect()
  75. num_queries = request.args.get("queries", 1, type=int)
  76. if num_queries < 1:
  77. num_queries = 1
  78. if num_queries > 500:
  79. num_queries = 500
  80. worlds = []
  81. for i in xrange(num_queries):
  82. wid = randint(1, 10000)
  83. result = connection.execute("SELECT * FROM world WHERE id = " + str(wid)).fetchone()
  84. worlds.append({'id': result[0], 'randomNumber': result[1]})
  85. connection.close()
  86. return json_response(worlds)
  87. @app.route("/dbsraw")
  88. def get_random_world_single_raw():
  89. connection = dbraw_engine.connect()
  90. wid = randint(1, 10000)
  91. result = connection.execute("SELECT * FROM world WHERE id = " + str(wid)).fetchone()
  92. worlds = {'id': result[0], 'randomNumber': result[1]}
  93. connection.close()
  94. return json_response(worlds)
  95. @app.route("/fortunes")
  96. def get_fortunes():
  97. fortunes = list(Fortune.query.all())
  98. fortunes.append(Fortune(id=0, message="Additional fortune added at request time."))
  99. fortunes.sort(key=attrgetter('message'))
  100. return render_template('fortunes.html', fortunes=fortunes)
  101. @app.route("/fortunesraw")
  102. def get_forutens_raw():
  103. res = dbraw_engine.execute("SELECT * FROM fortune")
  104. fortunes = res.fetchall()
  105. res.close()
  106. fortunes.append(Fortune(id=0, message="Additional fortune added at request time."))
  107. fortunes.sort(key=attrgetter('message'))
  108. return render_template('fortunes.html', fortunes=fortunes)
  109. @app.route("/updates")
  110. def updates():
  111. """Test 5: Database Updates"""
  112. num_queries = request.args.get('queries', 1, type=int)
  113. if num_queries < 1:
  114. num_queries = 1
  115. if num_queries > 500:
  116. num_queries = 500
  117. worlds = []
  118. rp = partial(randint, 1, 10000)
  119. ids = [rp() for _ in xrange(num_queries)]
  120. ids.sort() # To avoid deadlock
  121. for id in ids:
  122. world = World.get(id)
  123. world.randomNumber = rp()
  124. worlds.append(world.serialize)
  125. res = json_response(worlds)
  126. db.session.commit()
  127. return res
  128. @app.route("/raw-updates")
  129. def raw_updates():
  130. """Test 5: Database Updates"""
  131. connection = dbraw_engine.connect()
  132. try:
  133. num_queries = request.args.get('queries', 1, type=int)
  134. if num_queries < 1:
  135. num_queries = 1
  136. if num_queries > 500:
  137. num_queries = 500
  138. worlds = []
  139. rp = partial(randint, 1, 10000)
  140. for i in xrange(num_queries):
  141. world = connection.execute("SELECT * FROM world WHERE id=%s", (rp(),)).fetchone()
  142. randomNumber = rp()
  143. worlds.append({'id': world['id'], 'randomNumber': randomNumber})
  144. connection.execute("UPDATE World SET randomNumber=%s WHERE id=%s", (randomNumber, world['id']))
  145. return json_response(worlds)
  146. finally:
  147. connection.close()
  148. @app.route('/plaintext')
  149. def plaintext():
  150. """Test 6: Plaintext"""
  151. response = make_response(b'Hello, World!')
  152. response.content_type = 'text/plain'
  153. return response
  154. try:
  155. import meinheld
  156. meinheld.server.set_access_logger(None)
  157. meinheld.set_keepalive(120)
  158. except ImportError:
  159. pass
  160. # entry point for debugging
  161. if __name__ == "__main__":
  162. app.run(debug=True)