app.py 5.6 KB

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