Skip to content
This repository was archived by the owner on Sep 25, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions battlebots/database/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@
engine.dispose()
session_factory = sessionmaker(bind=engine)
Session = _scoped_session(session_factory)

session = Session()
session = None


@contextmanager
def scoped_session():
"""Provide a transactional scope around a series of operations."""
try:
yield session
session.commit()
yield Session()
Session.commit()
except:
logging.exception("Database had to do a rollback.")
session.rollback()
Session.rollback()
raise
finally:
Session.remove()


# Registers listeners (Don't remove this import!)
Expand Down
5 changes: 3 additions & 2 deletions battlebots/database/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging

from battlebots import config
from battlebots.database import session, scoped_session
from battlebots.database import Session, scoped_session
from battlebots.database.models import Bot


Expand Down Expand Up @@ -37,7 +37,8 @@ def remove_bot(user, botname):
% (user.nickname, botname, code_dir))
pass

bot = session.query(Bot).filter_by(user=user, name=botname).one_or_none()
bot = Session.query(Bot).filter_by(user=user, name=botname).one_or_none()
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use a with scoped_session() as db: here? If not, why?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we shouldn't need them on queries since those should not cause errors that require a session-rollback.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct, but at that point, there isn't an open session as Session() is only called in 2 places: before every Flask request handling and at the start of a scoped transaction. So wrapping that bit in a scoped_session block would open a session, and rollback if the query errors (which the ORM should ignore as there are no open transacation).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit/rollback part would indeed be unnecessary, so maybe we can make two kinds of context managers? Or maybe change Session.query(...) to Session().query(...)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That last wouldnt close that session connection then?
On 8 Apr 2016 11:00, "Stijn Seghers" notifications@github.com wrote:

In battlebots/database/access.py
#85 (comment):

@@ -37,7 +37,8 @@ def remove_bot(user, botname):
% (user.nickname, botname, code_dir))
pass

  • bot = session.query(Bot).filter_by(user=user, name=botname).one_or_none()

The commit/rollback part would indeed be unnecessary, so maybe we can make
two kinds of context managers? Or maybe change Session.query(...) to
Session().query(...)?


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
https://github.com/ZeusWPI/aichallenge/pull/85/files/1478b56574b04b5a61ef6433eb7d796aa0f7b628#r58997827

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opening a session for each request certainly seems the way to go, as people keep recommending it. It's definitely the most scalable and least bugprone way to do it. We should attempt this and not call it quits before we manage to do it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@silox: I just reread your first comments. Why wouldn't there be an open session? If we chose (2), than either the ranker or the web server should have opened one. Otherwise this code shouldn't be called in the first place. Right?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Procrat The ranker and webserver don't share their sessions, as they both use different enginges. But you are right that there should a session should be available because the Session object is connected to a session-factory.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Procrat Yes! Good thinking, that should indeed be the case and fix this
problem
On 8 Apr 2016 11:26, "Stijn Seghers" notifications@github.com wrote:

In battlebots/database/access.py
#85 (comment):

@@ -37,7 +37,8 @@ def remove_bot(user, botname):
% (user.nickname, botname, code_dir))
pass

  • bot = session.query(Bot).filter_by(user=user, name=botname).one_or_none()

@silox https://github.com/Silox: I just reread your first comments. Why
wouldn't there be an open session? If we chose (2), than either the ranker
or the web server should have opened one. Otherwise this code shouldn't be
called in the first place. Right?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
https://github.com/ZeusWPI/aichallenge/pull/85/files/1478b56574b04b5a61ef6433eb7d796aa0f7b628#r59000580


if bot is None:
logging.warning(
'Trying to remove a bot that does not exist. User:{}, Bot:{}'
Expand Down
4 changes: 2 additions & 2 deletions battlebots/database/listeners.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from sqlalchemy import event

from battlebots.database import session
from battlebots.database import Session
from battlebots.database.models import MatchParticipation
from battlebots.ranker.elo import elo_diff


@event.listens_for(session, 'before_commit')
@event.listens_for(Session, 'before_commit')
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Untested, no idea how this works.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will error iirc, I have tried before.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to test this locally this evening

def update_bot_ratings(session):
# If anyone finds a better way to update the ratings, please do

Expand Down
4 changes: 2 additions & 2 deletions battlebots/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from sqlalchemy.ext.associationproxy import association_proxy

from battlebots import backports, config, sandbox
from battlebots.database import session
from battlebots.database import Session
from battlebots.ranker.elo import DEFAULT_SCORE

Base = declarative_base()
Expand Down Expand Up @@ -152,7 +152,7 @@ def loss_percentage(self):

@property
def rank(self):
bots = enumerate(session.query(Bot).order_by(desc(Bot.score)).all())
bots = enumerate(Session.query(Bot).order_by(desc(Bot.score)).all())
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, scoped_session? If not, why?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will work I think, as this example is somewhere to be found in the docs.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as #85 (comment), but this is a hard one as this is called from the ranker as well as from the webapp.

return next(dropwhile(lambda bot: bot[1] != self, bots))[0]


Expand Down
9 changes: 4 additions & 5 deletions battlebots/database/test_populate.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import datetime as d

from battlebots.database import session
from battlebots.database import scoped_session
from battlebots.database.models import User, Bot, Match, MatchParticipation

user1 = User('tester1', 'test1@mail.com', 'test_pw_1')
Expand All @@ -17,7 +17,6 @@

l = [user1, user2, bot1, bot1, match1]

for x in l:
session.add(x)

session.commit()
with scoped_session() as db:
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit doesn't seem necesarry here as the scoped_session already commits

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:pompom:

for x in l:
db.add(x)
3 changes: 2 additions & 1 deletion battlebots/ranker/ranker.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

from battlebots import backports, config
from battlebots.arbiter import arbiter
from battlebots.database import access, session as db, scoped_session
from battlebots.database import access as db
from battlebots.database import scoped_session
from battlebots.database.models import Bot, Match, MatchParticipation

GRAPH_WANDERLUST = 0
Expand Down
10 changes: 9 additions & 1 deletion battlebots/web/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,15 @@
)


app.before_request(lambda: Session.remove())
@app.before_request
def before_request():
Session()


@app.teardown_request
def teardown_request(exception):
Session.commit()
Session.remove()

from battlebots.web import views # NOQA
from battlebots.web.views import bots # NOQA
4 changes: 2 additions & 2 deletions battlebots/web/forms/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from battlebots.arbiter import arbiter
from battlebots.database.models import User, PASSWORD_LENGTH, NICKNAME_LENGTH
from battlebots.web.validators import NonDuplicate
from battlebots.database import session
from battlebots.database import Session


class LoginForm(Form):
Expand All @@ -19,7 +19,7 @@ def validate(self):
if not rv:
return rv

user = session.query(User).filter_by(nickname=self.nickname.data).one_or_none()
user = Session.query(User).filter_by(nickname=self.nickname.data).one_or_none()
if user is None:
self.nickname.errors.append('User unknown.')
return False
Expand Down
4 changes: 2 additions & 2 deletions battlebots/web/validators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from wtforms.validators import ValidationError

from battlebots.database import session
from battlebots.database import Session
from battlebots.database.models import User

MAX_FILE_AMOUNT = 50
Expand All @@ -13,7 +13,7 @@ def __init__(self, class_, attribute):

def __call__(self, _, field):

user = session.query(self.class_).filter(
user = Session.query(self.class_).filter(
getattr(self.class_, self.attribute) == field.data
).first()

Expand Down
12 changes: 6 additions & 6 deletions battlebots/web/views/bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from werkzeug import secure_filename

from battlebots import config
from battlebots.database import session
from battlebots.database import Session
from battlebots.database import access as db
from battlebots.database.models import Bot, Match, User
from battlebots.web import app
Expand Down Expand Up @@ -35,8 +35,8 @@ def update_bot(username, botname):
abort(400) # Should not happen

form = UpdateBotForm()
user = session.query(User).filter_by(nickname=username).one_or_none()
bot = session.query(Bot).filter_by(user=user, name=botname).one_or_none()
user = Session.query(User).filter_by(nickname=username).one_or_none()
bot = Session.query(Bot).filter_by(user=user, name=botname).one_or_none()

if user is None:
flash('User {} does not exist.')
Expand Down Expand Up @@ -80,12 +80,12 @@ def remove_bot(username, botname):
@app.route('/bots/<username>/<botname>', methods=('GET',))
def bot_page(username, botname):

user = session.query(User).filter_by(nickname=username).one_or_none()
user = Session.query(User).filter_by(nickname=username).one_or_none()
if user is None:
flash('User {} does not exist.')
return redirect(url_for('users'))

bot = session.query(Bot).filter_by(user=user, name=botname).one_or_none()
bot = Session.query(Bot).filter_by(user=user, name=botname).one_or_none()
if bot is None:
flash('{} does not exist or does not belong to {}'
.format(botname, username))
Expand All @@ -97,7 +97,7 @@ def bot_page(username, botname):

@app.route('/matches/<matchid>')
def match_page(matchid):
match = session.query(Match).filter_by(id=matchid).one_or_none()
match = Session.query(Match).filter_by(id=matchid).one_or_none()

if match is None:
flash('Match with id {} does not exist.'.format(matchid))
Expand Down
10 changes: 5 additions & 5 deletions battlebots/web/views/users.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask import render_template, request, redirect, url_for, flash, abort
from flask.ext.login import login_required, login_user, logout_user, current_user

from battlebots.database import session
from battlebots.database import Session
from battlebots.database import access as db
from battlebots.database.models import User
from battlebots.web import app, lm
Expand All @@ -10,13 +10,13 @@

@app.route('/users/')
def users():
users_ = session.query(User).order_by(User.nickname).all()
users_ = Session.query(User).order_by(User.nickname).all()
return render_template('users/users.html', users=users_)


@app.route('/users/<username>')
def user_page(username):
user = session.query(User).filter_by(nickname=username).one_or_none()
user = Session.query(User).filter_by(nickname=username).one_or_none()

if user is None:
flash('User with name {} does not exist.'.format(username))
Expand All @@ -35,7 +35,7 @@ def profile():
def login():
form = LoginForm()
if form.validate_on_submit():
user = session.query(User).filter_by(nickname=form.nickname.data).first()
user = Session.query(User).filter_by(nickname=form.nickname.data).first()
if user is None:
abort(513) # shouldn't happen

Expand Down Expand Up @@ -83,4 +83,4 @@ def unauthorized_handler():

@lm.user_loader
def load_user(id):
return session.query(User).filter(User.id == id).one_or_none()
return Session.query(User).filter(User.id == id).one_or_none()
6 changes: 3 additions & 3 deletions battlebots/web/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from battlebots.web import app
from battlebots.web.pagination_utils import paginate
from battlebots.database import session
from battlebots.database import Session
from battlebots.database.models import Bot, Match


Expand All @@ -15,14 +15,14 @@ def home():

@app.route('/ranking')
def ranking():
bots = session.query(Bot).order_by(desc(Bot.score))
bots = Session.query(Bot).order_by(desc(Bot.score))
ranked_bots = enumerate(bots)
return render_template('ranking.html', bots=ranked_bots)


@app.route('/matches/')
def matches():
matches_ = session.query(Match).order_by(desc(Match.id))
matches_ = Session.query(Match).order_by(desc(Match.id))
paginated_matches_ = paginate(matches_)

return render_template('matches.html', paginated_matches=paginated_matches_)
Expand Down