Merge ~cjwatson/launchpad:number-cruncher-transactions into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 9bc4751b31d0fc91750f5cd3675cae284f43178a
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:number-cruncher-transactions
Merge into: launchpad:master
Diff against target: 91 lines (+16/-2)
2 files modified
lib/lp/services/statsd/numbercruncher.py (+11/-2)
lib/lp/services/statsd/tests/test_numbercruncher.py (+5/-0)
Reviewer Review Type Date Requested Status
Thiago F. Pappacena (community) Approve
Review via email: mp+393546@code.launchpad.net

Commit message

Abort transaction after each number-cruncher loop

Description of the change

We only read from the database, but if we don't end our transaction from time to time then we can end up with incorrect graphs and very long transactions.

To post a comment you must log in.
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Do you think it worth adding a comment on `NumberCruncher` class to warn future travelers that we always abort transaction?

Just in case we ever try to use it somewhere outside numbercruncher.tac, and end up with data not being persisted at database.

review: Approve
9bc4751... by Colin Watson

Add comment about transaction handling

Revision history for this message
Colin Watson (cjwatson) wrote :

That seems reasonable, thanks. I've updated the docstrings a bit.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/services/statsd/numbercruncher.py b/lib/lp/services/statsd/numbercruncher.py
2index 0a0552c..85fa2cd 100644
3--- a/lib/lp/services/statsd/numbercruncher.py
4+++ b/lib/lp/services/statsd/numbercruncher.py
5@@ -10,6 +10,7 @@ __all__ = ['NumberCruncher']
6
7 import logging
8
9+import transaction
10 from twisted.application import service
11 from twisted.internet import (
12 defer,
13@@ -68,7 +69,10 @@ class NumberCruncher(service.Service):
14 return loop, stopping_deferred
15
16 def updateBuilderQueues(self):
17- """Update statsd with the build queue lengths."""
18+ """Update statsd with the build queue lengths.
19+
20+ This aborts the current transaction before returning.
21+ """
22 self.logger.debug("Updating build queue stats.")
23 queue_details = getUtility(IBuilderSet).getBuildQueueSizes()
24 for queue_type, contents in queue_details.items():
25@@ -79,6 +83,7 @@ class NumberCruncher(service.Service):
26 self.logger.debug("{}: {}".format(gauge_name, value[0]))
27 self.statsd_client.gauge(gauge_name, value[0])
28 self.logger.debug("Build queue stats update complete.")
29+ transaction.abort()
30
31 def _updateBuilderCounts(self):
32 """Update statsd with the builder statuses.
33@@ -114,9 +119,13 @@ class NumberCruncher(service.Service):
34 self.logger.debug("Builder stats update complete.")
35
36 def updateBuilderStats(self):
37- """Statistics that require builder knowledge to be updated."""
38+ """Statistics that require builder knowledge to be updated.
39+
40+ This aborts the current transaction before returning.
41+ """
42 self.builder_factory.update()
43 self._updateBuilderCounts()
44+ transaction.abort()
45
46 def startService(self):
47 self.logger.info("Starting number-cruncher service.")
48diff --git a/lib/lp/services/statsd/tests/test_numbercruncher.py b/lib/lp/services/statsd/tests/test_numbercruncher.py
49index c5a4ff6..ede74e1 100644
50--- a/lib/lp/services/statsd/tests/test_numbercruncher.py
51+++ b/lib/lp/services/statsd/tests/test_numbercruncher.py
52@@ -20,6 +20,7 @@ from lp.buildmaster.enums import BuilderCleanStatus
53 from lp.buildmaster.interactor import BuilderSlave
54 from lp.buildmaster.interfaces.processor import IProcessorSet
55 from lp.buildmaster.tests.mock_slaves import OkSlave
56+from lp.services.database.isolation import is_transaction_in_progress
57 from lp.services.statsd.numbercruncher import NumberCruncher
58 from lp.services.statsd.tests import StatsMixin
59 from lp.testing import TestCaseWithFactory
60@@ -46,6 +47,7 @@ class TestNumberCruncher(StatsMixin, TestCaseWithFactory):
61 manager.builder_factory.update()
62 manager.updateBuilderStats()
63
64+ self.assertFalse(is_transaction_in_progress())
65 self.assertEqual(8, self.stats_client.gauge.call_count)
66 for call in self.stats_client.mock.gauge.call_args_list:
67 self.assertIn('386', call[0][0])
68@@ -61,6 +63,7 @@ class TestNumberCruncher(StatsMixin, TestCaseWithFactory):
69 manager.builder_factory.update()
70 manager.updateBuilderStats()
71
72+ self.assertFalse(is_transaction_in_progress())
73 self.assertEqual(12, self.stats_client.gauge.call_count)
74 i386_calls = [c for c in self.stats_client.gauge.call_args_list
75 if '386' in c[0][0]]
76@@ -80,6 +83,7 @@ class TestNumberCruncher(StatsMixin, TestCaseWithFactory):
77 manager.builder_factory.update()
78 manager.updateBuilderStats()
79
80+ self.assertFalse(is_transaction_in_progress())
81 self.assertEqual(12, self.stats_client.gauge.call_count)
82 calls = [c[0] for c in self.stats_client.gauge.call_args_list
83 if 'amd64' in c[0][0]]
84@@ -113,6 +117,7 @@ class TestNumberCruncher(StatsMixin, TestCaseWithFactory):
85 manager.builder_factory.update()
86 manager.updateBuilderQueues()
87
88+ self.assertFalse(is_transaction_in_progress())
89 self.assertEqual(2, self.stats_client.gauge.call_count)
90 self.assertThat(
91 [x[0] for x in self.stats_client.gauge.call_args_list],

Subscribers

People subscribed via source and target branches

to status/vote changes: