Skip to content

Instantly share code, notes, and snippets.

@btel
Created November 19, 2020 12:50
Show Gist options
  • Save btel/a808d8ef4a6a868a1c952805a0e453f8 to your computer and use it in GitHub Desktop.
Save btel/a808d8ef4a6a868a1c952805a0e453f8 to your computer and use it in GitHub Desktop.
testing race conditions in quetz create_version

Insert concurrenlty package versions in quetz DB

Test with:

python test_lock.py

(runs with sqlite)

or

QUETZ_LOG_LEVEL=debug QUETZ_TEST_DATABASE="postgresql://postgres:mysecretpassword@localhost:5432/test_quetz" python test_lock.py

(runs with postgres)

from quetz.db_models import Package, Channel, User
from quetz.dao import Dao
from quetz.database import get_session
from quetz.config import Config
from quetz.versionorder import VersionOrder
import sys
import os
import logging
logging.basicConfig(level=logging.DEBUG)
import uuid
user = User(id=uuid.uuid4().bytes)
channel_name = "test-channel-{}".format(str(uuid.uuid4())[:5])
package_name = "test-package"
channel_data = Channel(name=channel_name, private=False)
package_data = Package(name=package_name)
db_url = os.environ.get("QUETZ_TEST_DATABASE")
import tempfile
if not db_url:
tmpdir = tempfile.mkdtemp()
db_url = f"sqlite:///{tmpdir}/sqlite.db"
print(f"using db {db_url}")
echo = False
db = get_session(db_url)
db.add(user)
dao = Dao(db)
dao.create_channel(channel_data, user.id, "owner")
package = dao.create_package(channel_name, package_data, user.id, "owner")
package_format = "tarbz2"
package_info = "{}"
#version = [
# ("0.1.0", 0),
# ("0.3.0", 2),
# ("0.2.0", 2),
#]
from random import choice
x = [0, 1, 2, 3, 4, 5]
version = list(set(
(f"{choice(x)}.{choice(x)}.{choice(x)}", choice(x)) for _ in range(50)))
print(version)
from threading import Thread
class worker(Thread):
def __init__(self, v):
self.v = v
super().__init__()
def run(self):
db = get_session(db_url, echo=echo)
dao = Dao(db)
#package_name = "test-package-" + str(uuid.uuid4())
#package_data = Package(name=package_name)
#package = dao.create_package(channel_name, package_data, user.id, "owner")
dao.create_version(
channel_name,
package_name,
package_format,
"linux-64",
self.v[0],
self.v[1],
"",
"",
package_info,
user.id,
)
db.close()
import time
class waiter(Thread):
def __init__(self):
self.v = v
super().__init__()
def run(self):
db = get_session(db_url, echo=True)
dao = Dao(db)
print(f"waiting {self.v}")
time.sleep(1)
print(f"awoken {self.v}")
dao.create_version(
channel_name,
package_name,
package_format,
"linux-64",
version[0][0],
version[0][1],
"",
"",
package_info,
user.id,
)
workers = [worker(v) for v in version[1:]]
for w in workers:
w.start()
for w in workers:
w.join()
res = dao.get_package_versions(package)
res_versions = [(VersionOrder(x[0].version), x[0].build_number) for x in res]
assert sorted(res_versions, reverse=True) == res_versions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment