Skip to content

Commit

Permalink
run process_release in a transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
azuline committed Oct 10, 2023
1 parent 0c0d262 commit bc58b89
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
36 changes: 36 additions & 0 deletions rose/cache/database.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import binascii
import logging
import random
import sqlite3
import time
from collections.abc import Iterator
from contextlib import contextmanager

Expand All @@ -19,6 +22,39 @@ def connect(c: Config) -> Iterator[sqlite3.Connection]:
conn.close()


@contextmanager
def transaction(conn: sqlite3.Connection) -> Iterator[sqlite3.Connection]:
"""
A simple context wrapper for a database transaction. If connection is null,
a new connection is created.
"""
tx_log_id = binascii.b2a_hex(random.randbytes(8)).decode()
start_time = time.time()

# If we're already in a transaction, don't create a nested transaction.
if conn.in_transaction:
logger.debug(f"Transaction {tx_log_id}. Starting nested transaction, NoOp.")
yield conn
logger.debug(
f"Transaction {tx_log_id}. End of nested transaction. "
f"Duration: {time.time() - start_time}."
)
return

logger.debug(f"Transaction {tx_log_id}. Starting transaction from conn.")
with conn:
# We BEGIN IMMEDIATE to avoid deadlocks, which pisses the hell out of me because no one's
# documenting this properly and SQLite just dies without respecting the timeout and without
# a reasonable error message. Absurd.
# - https://sqlite.org/forum/forumpost/a3db6dbff1cd1d5d
conn.execute("BEGIN IMMEDIATE")
yield conn
logger.debug(
f"Transaction {tx_log_id}. End of transaction from conn. "
f"Duration: {time.time() - start_time}."
)


def connect_fn(c: Config) -> sqlite3.Connection:
"""Non-context manager version of connect."""
conn = sqlite3.connect(
Expand Down
4 changes: 2 additions & 2 deletions rose/cache/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import uuid6

from rose.cache.database import connect
from rose.cache.database import connect, transaction
from rose.foundation.conf import Config
from rose.tagger import AudioFile

Expand Down Expand Up @@ -84,7 +84,7 @@ def update_cache_for_release(c: Config, release_dir: Path) -> Path:
Returns the new release_dir if a rename occurred; otherwise, returns the same release_dir.
"""
with connect(c) as conn:
with connect(c) as conn, transaction(conn) as conn:
# The release will be updated based on the album tags of the first track.
release: CachedRelease | None = None
# But first, parse the release_id from the directory name. If the directory name does not
Expand Down
Empty file added rose/cache/process_test.py
Empty file.

0 comments on commit bc58b89

Please sign in to comment.