Skip to content
This repository has been archived by the owner on Jul 28, 2020. It is now read-only.

Commit

Permalink
fix race conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
roblaszczak committed Nov 2, 2019
1 parent 9a28235 commit bdc2102
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 19 deletions.
2 changes: 1 addition & 1 deletion pkg/kafka/pubsub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func newPubSub(t *testing.T, marshaler kafka.MarshalerUnmarshaler, consumerGroup
saramaConfig.Producer.RequiredAcks = sarama.WaitForAll
saramaConfig.ChannelBufferSize = 10240
saramaConfig.Consumer.Group.Heartbeat.Interval = time.Millisecond * 500
saramaConfig.Consumer.Group.Rebalance.Timeout = time.Millisecond * 500
saramaConfig.Consumer.Group.Rebalance.Timeout = time.Second * 3

var subscriber message.Subscriber

Expand Down
49 changes: 31 additions & 18 deletions pkg/kafka/subscriber.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,10 @@ func (s *Subscriber) consumeGroupMessages(
return nil, errors.Wrap(err, "cannot create consumer group client")
}

closed := make(chan struct{})
groupClosed := make(chan struct{})

go s.handleGroupErrors(group, logFields, closed)
handleGroupErrorsCtx, cancelHandleGroupErrors := context.WithCancel(context.Background())
handleGroupErrorsDone := s.handleGroupErrors(handleGroupErrorsCtx, group, logFields)

handler := consumerGroupHandler{
ctx: ctx,
Expand All @@ -292,34 +293,46 @@ func (s *Subscriber) consumeGroupMessages(
s.logger.Debug("Consume stopped without any error", logFields)
}

cancelHandleGroupErrors()
<-handleGroupErrorsDone

if err := group.Close(); err != nil {
s.logger.Info("Group close with error", logFields.Add(watermill.LogFields{"err": err.Error()}))
}

s.logger.Info("Consuming done", logFields)
close(closed)
close(groupClosed)
}()

return closed, nil
return groupClosed, nil
}

func (s *Subscriber) handleGroupErrors(group sarama.ConsumerGroup, logFields watermill.LogFields, closed chan struct{}) {
errs := group.Errors()
func (s *Subscriber) handleGroupErrors(
ctx context.Context,
group sarama.ConsumerGroup,
logFields watermill.LogFields,
) chan struct{} {
done := make(chan struct{})

for {
select {
case err := <-errs:
if err == nil {
continue
go func() {
defer close(done)
errs := group.Errors()

for {
select {
case err := <-errs:
if err == nil {
continue
}

s.logger.Error("Sarama internal error", err, logFields)
case <-ctx.Done():
return
}

s.logger.Error("Sarama internal error", err, logFields)
case <-closed:
return
case <-s.closing:
return
}
}
}()

return done
}

func (s *Subscriber) consumeWithoutConsumerGroups(
Expand Down

0 comments on commit bdc2102

Please sign in to comment.