Blob Blame History Raw
From 2aa92ed0dd8004df33b3c6de62b047caa895f96a Mon Sep 17 00:00:00 2001
From: Ralph Bean <rbean@redhat.com>
Date: Tue, 20 Jan 2015 09:49:25 -0500
Subject: [PATCH] Randomize preference list per-thread.

I'm noticing a weird behavior at FMN after restart.  All the threads lock on
each other and do basically zero work as they wait for one of them to query
pkgdb for individual users one after another.  Thread #1 queries pkgdb for
ralph's packages and Threads 2-10 all wait for it to be done before moving on
to the next preference to check.

This should make each thread step through the preferences in a random order
each time.  This means that while Thread #1 queries pkgdb for ralph's packages,
Thread #2 will query pkgdb for pingou's packages, and Thread #3 will query
pkgdb for till's packages, ..etc.  (Eventually all those package owning
relationships get cached and we stop querying pkgdb).
---
 fmn/consumer/consumer.py | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/fmn/consumer/consumer.py b/fmn/consumer/consumer.py
index 8a05489..21e8de4 100644
--- a/fmn/consumer/consumer.py
+++ b/fmn/consumer/consumer.py
@@ -1,6 +1,7 @@
 # An example fedmsg koji consumer
 
 import threading
+import random
 
 import fedmsg.consumers
 import fmn.lib
@@ -164,7 +165,15 @@ class FMNConsumer(fedmsg.consumers.FedmsgConsumer):
         # With cache management done, we can move on to the real work.
         # Compute, based on our in-memory cache of preferences, who we think
         # should receive this message.
-        results = fmn.lib.recipients(self.cached_preferences, msg,
+
+        # First, make a thread-local copy of our shared cached prefs
+        preferences = list(self.cached_preferences)
+        # Shuffle it so that not all threads step through the list in the same
+        # order.  This should cut down on competition for the dogpile lock when
+        # getting pkgdb info at startup.
+        random.shuffle(preferences)
+        # And do the real work of comparing every rule against the message.
+        results = fmn.lib.recipients(preferences, msg,
                                      self.valid_paths, self.hub.config)
 
         # Let's look at the results of our matching operation and send stuff
-- 
2.1.0