瀏覽代碼

Merge pull request #529 from Shopify/fix-consumer-race

Fix consumer race panic on close
Evan Huus 9 年之前
父節點
當前提交
9c6285c339
共有 1 個文件被更改,包括 45 次插入37 次删除
  1. 45 37
      consumer.go

+ 45 - 37
consumer.go

@@ -572,10 +572,7 @@ func (bc *brokerConsumer) subscriptionConsumer() {
 
 
 	// the subscriptionConsumer ensures we will get nil right away if no new subscriptions is available
 	// the subscriptionConsumer ensures we will get nil right away if no new subscriptions is available
 	for newSubscriptions := range bc.newSubscriptions {
 	for newSubscriptions := range bc.newSubscriptions {
-		for _, child := range newSubscriptions {
+		bc.updateSubscriptions(newSubscriptions)
-			bc.subscriptions[child] = none{}
-			Logger.Printf("consumer/broker/%d added subscription to %s/%d\n", bc.broker.ID(), child.topic, child.partition)
-		}
 
 
 		if len(bc.subscriptions) == 0 {
 		if len(bc.subscriptions) == 0 {
 			// We're about to be shut down or we're about to receive more subscriptions.
 			// We're about to be shut down or we're about to receive more subscriptions.
@@ -601,8 +598,12 @@ func (bc *brokerConsumer) subscriptionConsumer() {
 	}
 	}
 }
 }
 
 
-func (bc *brokerConsumer) handleResponses() {
+func (bc *brokerConsumer) updateSubscriptions(newSubscriptions []*partitionConsumer) {
-	// handles the response codes left for us by our subscriptions, and abandons ones that have been closed
+	for _, child := range newSubscriptions {
+		bc.subscriptions[child] = none{}
+		Logger.Printf("consumer/broker/%d added subscription to %s/%d\n", bc.broker.ID(), child.topic, child.partition)
+	}
+
 	for child := range bc.subscriptions {
 	for child := range bc.subscriptions {
 		select {
 		select {
 		case <-child.dying:
 		case <-child.dying:
@@ -610,37 +611,44 @@ func (bc *brokerConsumer) handleResponses() {
 			close(child.trigger)
 			close(child.trigger)
 			delete(bc.subscriptions, child)
 			delete(bc.subscriptions, child)
 		default:
 		default:
-			result := child.responseResult
+			break
-			child.responseResult = nil
+		}
-
+	}
-			switch result {
+}
-			case nil:
+
-				break
+func (bc *brokerConsumer) handleResponses() {
-			case errTimedOut:
+	// handles the response codes left for us by our subscriptions, and abandons ones that have been closed
-				Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because consuming was taking too long\n",
+	for child := range bc.subscriptions {
-					bc.broker.ID(), child.topic, child.partition)
+		result := child.responseResult
-				delete(bc.subscriptions, child)
+		child.responseResult = nil
-			case ErrOffsetOutOfRange:
+
-				// there's no point in retrying this it will just fail the same way again
+		switch result {
-				// shut it down and force the user to choose what to do
+		case nil:
-				child.sendError(result)
+			break
-				Logger.Printf("consumer/%s/%d shutting down because %s\n", child.topic, child.partition, result)
+		case errTimedOut:
-				close(child.trigger)
+			Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because consuming was taking too long\n",
-				delete(bc.subscriptions, child)
+				bc.broker.ID(), child.topic, child.partition)
-			case ErrUnknownTopicOrPartition, ErrNotLeaderForPartition, ErrLeaderNotAvailable:
+			delete(bc.subscriptions, child)
-				// not an error, but does need redispatching
+		case ErrOffsetOutOfRange:
-				Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n",
+			// there's no point in retrying this it will just fail the same way again
-					bc.broker.ID(), child.topic, child.partition, result)
+			// shut it down and force the user to choose what to do
-				child.trigger <- none{}
+			child.sendError(result)
-				delete(bc.subscriptions, child)
+			Logger.Printf("consumer/%s/%d shutting down because %s\n", child.topic, child.partition, result)
-			default:
+			close(child.trigger)
-				// dunno, tell the user and try redispatching
+			delete(bc.subscriptions, child)
-				child.sendError(result)
+		case ErrUnknownTopicOrPartition, ErrNotLeaderForPartition, ErrLeaderNotAvailable:
-				Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n",
+			// not an error, but does need redispatching
-					bc.broker.ID(), child.topic, child.partition, result)
+			Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n",
-				child.trigger <- none{}
+				bc.broker.ID(), child.topic, child.partition, result)
-				delete(bc.subscriptions, child)
+			child.trigger <- none{}
-			}
+			delete(bc.subscriptions, child)
+		default:
+			// dunno, tell the user and try redispatching
+			child.sendError(result)
+			Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n",
+				bc.broker.ID(), child.topic, child.partition, result)
+			child.trigger <- none{}
+			delete(bc.subscriptions, child)
 		}
 		}
 	}
 	}
 }
 }