You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

71 lines
1.9 KiB

  1. package sub_client
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/seaweedfs/seaweedfs/weed/pb"
  6. "github.com/seaweedfs/seaweedfs/weed/pb/mq_pb"
  7. "sync"
  8. )
  9. type EachMessageFunc func(key, value []byte) (shouldContinue bool)
  10. type FinalFunc func()
  11. func (sub *TopicSubscriber) Subscribe(eachMessageFn EachMessageFunc, finalFn FinalFunc) error {
  12. var wg sync.WaitGroup
  13. for _, brokerPartitionAssignment := range sub.brokerPartitionAssignments {
  14. brokerAddress := brokerPartitionAssignment.LeaderBroker
  15. grpcConnection, err := pb.GrpcDial(context.Background(), brokerAddress, true, sub.grpcDialOption)
  16. if err != nil {
  17. return fmt.Errorf("dial broker %s: %v", brokerAddress, err)
  18. }
  19. brokerClient := mq_pb.NewSeaweedMessagingClient(grpcConnection)
  20. subscribeClient, err := brokerClient.Subscribe(context.Background(), &mq_pb.SubscribeRequest{
  21. Consumer: &mq_pb.SubscribeRequest_Consumer{
  22. ConsumerGroup: sub.config.ConsumerGroup,
  23. ConsumerId: sub.config.ConsumerId,
  24. },
  25. Cursor: &mq_pb.SubscribeRequest_Cursor{
  26. Topic: &mq_pb.Topic{
  27. Namespace: sub.namespace,
  28. Name: sub.topic,
  29. },
  30. Partition: &mq_pb.Partition{
  31. RingSize: brokerPartitionAssignment.Partition.RingSize,
  32. RangeStart: brokerPartitionAssignment.Partition.RangeStart,
  33. RangeStop: brokerPartitionAssignment.Partition.RangeStop,
  34. },
  35. },
  36. })
  37. if err != nil {
  38. return fmt.Errorf("create subscribe client: %v", err)
  39. }
  40. wg.Add(1)
  41. go func() {
  42. defer wg.Done()
  43. if finalFn != nil {
  44. defer finalFn()
  45. }
  46. for {
  47. resp, err := subscribeClient.Recv()
  48. if err != nil {
  49. fmt.Printf("subscribe error: %v\n", err)
  50. return
  51. }
  52. if resp.Message == nil {
  53. continue
  54. }
  55. switch m := resp.Message.(type) {
  56. case *mq_pb.SubscribeResponse_Data:
  57. if !eachMessageFn(m.Data.Key, m.Data.Value) {
  58. return
  59. }
  60. case *mq_pb.SubscribeResponse_Ctrl:
  61. // ignore
  62. }
  63. }
  64. }()
  65. }
  66. wg.Wait()
  67. return nil
  68. }