database: Remove retry_on_conflict helper and default to autocommit

All our usage was of a single query anyway, so autocommit is easier to handle.
You can still opt into a longer transaction using the transaction() helper.
pull/42/head
Mike Lang 6 years ago
parent 0a31ba2590
commit 7976cb3736

@ -5,6 +5,8 @@ Note that this code requires psycopg2 and psycogreen, but the common module
as a whole does not to avoid needing to install them for components that don't need it. as a whole does not to avoid needing to install them for components that don't need it.
""" """
from contextlib import contextmanager
import psycopg2 import psycopg2
import psycopg2.extensions import psycopg2.extensions
import psycopg2.extras import psycopg2.extras
@ -70,16 +72,15 @@ class DBManager(object):
the initial conn used to apply the schema, and you should use a real conn pool for the initial conn used to apply the schema, and you should use a real conn pool for
any non-trivial use. any non-trivial use.
Returned conns are set to seralizable isolation level, and use NamedTupleCursor cursors. Returned conns are set to seralizable isolation level, autocommit, and use NamedTupleCursor cursors.
""" """
def __init__(self, **connect_kwargs): def __init__(self, **connect_kwargs):
patch_psycopg() patch_psycopg()
self.conns = [] self.conns = []
self.connect_kwargs = connect_kwargs self.connect_kwargs = connect_kwargs
conn = self.get_conn() conn = self.get_conn()
with conn: with transaction(conn):
with conn.cursor() as cur: query(conn, SCHEMA)
cur.execute(SCHEMA)
self.put_conn(conn) self.put_conn(conn)
def put_conn(self, conn): def put_conn(self, conn):
@ -93,24 +94,23 @@ class DBManager(object):
# we don't care about the performance concerns and everything we do is easily retryable. # we don't care about the performance concerns and everything we do is easily retryable.
# This shouldn't matter in practice anyway since everything we're doing is either read-only # This shouldn't matter in practice anyway since everything we're doing is either read-only
# searches or targetted single-row updates. # searches or targetted single-row updates.
conn.set_session(psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE) conn.isolation_level = psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE
conn.autocommit = True
return conn return conn
def retry_on_conflict(conn, func, *args, **kwargs): @contextmanager
"""Run func(conn, *args, **kwargs) in a transaction up to max_tries (given as kwarg) times def transaction(conn):
(at least once, default 5), retrying if it raises an error indicating a transaction conflict. """Helper context manager that runs the code block as a single database transaction
After max_tries, raises TransactionRollbackError. instead of in autocommit mode. The only difference between this and "with conn" is
""" that we explicitly disable then re-enable autocommit."""
max_tries = kwargs.pop('max_tries', 5) old_autocommit = conn.autocommit
for _ in range(max_tries - 1): conn.autocommit = False
try: try:
with conn: with conn:
return func(conn) yield
except psycopg2.extensions.TransactionRollbackError: finally:
pass conn.autocommit = old_autocommit
with conn:
return func(conn)
def query(conn, query, *args, **kwargs): def query(conn, query, *args, **kwargs):

Loading…
Cancel
Save