I deployed Gavel to Heroku on a hobby dyno, and I'm seeing a ton of crashes when voting on items. We had around 170 items and 10 annotators spamming the app simultaneously, and the app would show an Internal Server Error quite regularly after voting.
2016-11-07T17:45:24.292366+00:00 app[web.1]: [2016-11-07 17:45:24,289] ERROR in app: Exception on /vote [POST]
2016-11-07T17:45:24.292378+00:00 app[web.1]: Traceback (most recent call last):
2016-11-07T17:45:24.292380+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
2016-11-07T17:45:24.292382+00:00 app[web.1]: context)
2016-11-07T17:45:24.292383+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute
2016-11-07T17:45:24.292384+00:00 app[web.1]: cursor.execute(statement, parameters)
2016-11-07T17:45:24.292385+00:00 app[web.1]: psycopg2.extensions.TransactionRollbackError: could not serialize access due to concurrent update
2016-11-07T17:45:24.292386+00:00 app[web.1]:
2016-11-07T17:45:24.292387+00:00 app[web.1]:
2016-11-07T17:45:24.292387+00:00 app[web.1]: The above exception was the direct cause of the following exception:
2016-11-07T17:45:24.292388+00:00 app[web.1]:
2016-11-07T17:45:24.292389+00:00 app[web.1]: Traceback (most recent call last):
2016-11-07T17:45:24.292390+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1988, in wsgi_app
2016-11-07T17:45:24.292391+00:00 app[web.1]: response = self.full_dispatch_request()
2016-11-07T17:45:24.292392+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1641, in full_dispatch_request
2016-11-07T17:45:24.292392+00:00 app[web.1]: rv = self.handle_user_exception(e)
2016-11-07T17:45:24.292393+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1544, in handle_user_exception
2016-11-07T17:45:24.292394+00:00 app[web.1]: reraise(exc_type, exc_value, tb)
2016-11-07T17:45:24.292420+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
2016-11-07T17:45:24.292422+00:00 app[web.1]: raise value
2016-11-07T17:45:24.292422+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1639, in full_dispatch_request
2016-11-07T17:45:24.292423+00:00 app[web.1]: rv = self.dispatch_request()
2016-11-07T17:45:24.292424+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1625, in dispatch_request
2016-11-07T17:45:24.292425+00:00 app[web.1]: return self.view_functionsrule.endpoint
2016-11-07T17:45:24.292426+00:00 app[web.1]: File "/app/gavel/controllers/judge.py", line 25, in decorated
2016-11-07T17:45:24.292427+00:00 app[web.1]: return f(*args, **kwargs)
2016-11-07T17:45:24.292428+00:00 app[web.1]: File "/app/gavel/controllers/judge.py", line 33, in decorated
2016-11-07T17:45:24.292429+00:00 app[web.1]: annotator = get_current_annotator()
2016-11-07T17:45:24.292429+00:00 app[web.1]: File "/app/gavel/controllers/judge.py", line 150, in get_current_annotator
2016-11-07T17:45:24.292430+00:00 app[web.1]: return Annotator.by_id(session.get(ANNOTATOR_ID, None))
2016-11-07T17:45:24.292430+00:00 app[web.1]: File "/app/gavel/models/annotator.py", line 59, in by_id
2016-11-07T17:45:24.292431+00:00 app[web.1]: annotator = cls.query.with_for_update().get(uid)
2016-11-07T17:45:24.292432+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 831, in get
2016-11-07T17:45:24.292432+00:00 app[web.1]: return self._get_impl(ident, loading.load_on_ident)
2016-11-07T17:45:24.292433+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 864, in _get_impl
2016-11-07T17:45:24.292433+00:00 app[web.1]: return fallback_fn(self, key)
2016-11-07T17:45:24.292434+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/loading.py", line 219, in load_on_ident
2016-11-07T17:45:24.292434+00:00 app[web.1]: return q.one()
2016-11-07T17:45:24.292435+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2718, in one
2016-11-07T17:45:24.292436+00:00 app[web.1]: ret = list(self)
2016-11-07T17:45:24.292436+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2761, in iter
2016-11-07T17:45:24.292437+00:00 app[web.1]: return self._execute_and_instances(context)
2016-11-07T17:45:24.292438+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2776, in _execute_and_instances
2016-11-07T17:45:24.292439+00:00 app[web.1]: result = conn.execute(querycontext.statement, self._params)
2016-11-07T17:45:24.292439+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 914, in execute
2016-11-07T17:45:24.292440+00:00 app[web.1]: return meth(self, multiparams, params)
2016-11-07T17:45:24.292441+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
2016-11-07T17:45:24.292441+00:00 app[web.1]: return connection._execute_clauseelement(self, multiparams, params)
2016-11-07T17:45:24.292442+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
2016-11-07T17:45:24.292443+00:00 app[web.1]: compiled_sql, distilled_params
2016-11-07T17:45:24.292443+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
2016-11-07T17:45:24.292444+00:00 app[web.1]: context)
2016-11-07T17:45:24.292445+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
2016-11-07T17:45:24.292445+00:00 app[web.1]: exc_info
2016-11-07T17:45:24.292446+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/util/compat.py", line 202, in raise_from_cause
2016-11-07T17:45:24.292447+00:00 app[web.1]: reraise(type(exception), exception, tb=exc_tb, cause=cause)
2016-11-07T17:45:24.292448+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/util/compat.py", line 185, in reraise
2016-11-07T17:45:24.292448+00:00 app[web.1]: raise value.with_traceback(tb)
2016-11-07T17:45:24.292449+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
2016-11-07T17:45:24.292450+00:00 app[web.1]: context)
2016-11-07T17:45:24.292450+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute
2016-11-07T17:45:24.292457+00:00 app[web.1]: cursor.execute(statement, parameters)
2016-11-07T17:45:24.292459+00:00 app[web.1]: sqlalchemy.exc.OperationalError: (psycopg2.extensions.TransactionRollbackError) could not serialize access due to concurrent update
2016-11-07T17:45:24.292548+00:00 app[web.1]: [SQL: 'SELECT annotator.id AS annotator_id, annotator.name AS annotator_name, annotator.email AS annotator_email, annotator.active AS annotator_active, annotator.read_welcome AS annotator_read_welcome, annotator.description AS annotator_description, annotator.secret AS annotator_secret, annotator.next_id AS annotator_next_id, annotator.updated AS annotator_updated, annotator.prev_id AS annotator_prev_id, annotator.alpha AS annotator_alpha, annotator.beta AS annotator_beta \nFROM annotator \nWHERE annotator.id = %(param_1)s FOR UPDATE'] [parameters: {'param_1': 6}]
Could this be an issue with limits in the hobby dyno or something else? Would be nice to know that this won't be an issue on game day in three weeks :D