batches.py: Don't pass SQLAlchemy objects between threads

SQLAlchemy objects can't be used from multiple threads - so when starting
threads for builds, pass the ComponentBuild id rather than the object.
(Note that despite the comment that the threads were sharing a session,
they weren't - what was passed to the thread was a scoped_session that
acts as a separate thread-local session per-thread.)

BUILD_COMPONENT_DB_SESSION_LOCK - a threading.Lock() object that was used
in a few places - but not nearly enough places to effectively lock usage
of a shared session - is removed.
This commit is contained in:
Owen W. Taylor
2020-11-09 11:56:38 -05:00
parent 4a3e6fb0fa
commit 5dcd63ebf9
4 changed files with 60 additions and 34 deletions

View File

@@ -172,6 +172,7 @@ class TestBatches:
start_next_batch_build(conf, module_build, builder)
# Batch number should increase.
module_build = models.ModuleBuild.get_by_id(db_session, 3)
assert module_build.batch == 2
# Make sure we only have one message returned for the one reused component
@@ -218,6 +219,8 @@ class TestBatches:
builder.recover_orphaned_artifact.return_value = []
start_next_batch_build(conf, module_build, builder)
module_build = models.ModuleBuild.get_by_id(db_session, 3)
# Batch number should increase.
assert module_build.batch == 2
# No component reuse messages should be returned
@@ -233,7 +236,15 @@ class TestBatches:
builder.build.side_effect = Exception("Something have gone terribly wrong")
component = mock.MagicMock()
start_build_component(db_session, builder, component)
component = models.ComponentBuild.from_component_name(
db_session, "perl-List-Compare", 3)
assert component.state != koji.BUILD_STATES["FAILED"]
start_build_component(db_session, builder, component.id)
component = models.ComponentBuild.from_component_name(
db_session, "perl-List-Compare", 3)
assert component.state == koji.BUILD_STATES["FAILED"]
@@ -264,6 +275,8 @@ class TestBatches:
builder.recover_orphaned_artifact.return_value = []
start_next_batch_build(conf, module_build, builder)
module_build = models.ModuleBuild.get_by_id(db_session, 3)
# Batch number should increase
assert module_build.batch == 2
@@ -292,6 +305,8 @@ class TestBatches:
mock_sbc.reset_mock()
# Complete the build
plc_component = models.ComponentBuild.from_component_name(
db_session, "perl-List-Compare", 3)
plc_component.state = koji.BUILD_STATES["COMPLETE"]
pt_component = models.ComponentBuild.from_component_name(
db_session, "perl-Tangerine", 3)
@@ -301,6 +316,9 @@ class TestBatches:
# Start the next build batch
start_next_batch_build(conf, module_build, builder)
module_build = models.ModuleBuild.get_by_id(db_session, 3)
# Batch number should increase
assert module_build.batch == 3
# Verify that tangerine was reused even though perl-Tangerine was rebuilt in the previous
@@ -344,6 +362,8 @@ class TestBatches:
builder.recover_orphaned_artifact.return_value = []
start_next_batch_build(conf, module_build, builder)
module_build = models.ModuleBuild.get_by_id(db_session, 3)
# Batch number should increase.
assert module_build.batch == 2
@@ -357,8 +377,8 @@ class TestBatches:
# Test the order of the scheduling
expected_calls = [
mock.call(db_session, builder, plc_component),
mock.call(db_session, builder, pt_component)
mock.call(db_session, builder, plc_component.id),
mock.call(db_session, builder, pt_component.id)
]
assert mock_sbc.mock_calls == expected_calls
@@ -379,6 +399,8 @@ class TestBatches:
builder = mock.MagicMock()
start_next_batch_build(conf, module_build, builder)
module_build = models.ModuleBuild.get_by_id(db_session, 3)
# Batch number should not increase.
assert module_build.batch == 2
# Make sure start build was called for the second component which wasn't reused
@@ -399,5 +421,7 @@ class TestBatches:
builder = mock.MagicMock()
builder.buildroot_ready.return_value = False
module_build = models.ModuleBuild.get_by_id(db_session, 3)
# Batch number should not increase.
assert module_build.batch == 1