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.

105 lines
3.0 KiB

1 week ago
  1. package agent
  2. import (
  3. "context"
  4. "github.com/seaweedfs/seaweedfs/weed/glog"
  5. "github.com/seaweedfs/seaweedfs/weed/mq/client/sub_client"
  6. "github.com/seaweedfs/seaweedfs/weed/mq/topic"
  7. "github.com/seaweedfs/seaweedfs/weed/pb/mq_agent_pb"
  8. "github.com/seaweedfs/seaweedfs/weed/pb/mq_pb"
  9. "github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
  10. "github.com/seaweedfs/seaweedfs/weed/util"
  11. "google.golang.org/grpc"
  12. "google.golang.org/grpc/credentials/insecure"
  13. "google.golang.org/protobuf/proto"
  14. )
  15. func (a *MessageQueueAgent) SubscribeRecord(stream mq_agent_pb.SeaweedMessagingAgent_SubscribeRecordServer) error {
  16. // the first message is the subscribe request
  17. // it should only contain the session id
  18. initMessage, err := stream.Recv()
  19. if err != nil {
  20. return err
  21. }
  22. subscriber := a.handleInitSubscribeRecordRequest(stream.Context(), initMessage.Init)
  23. var lastErr error
  24. executors := util.NewLimitedConcurrentExecutor(int(subscriber.SubscriberConfig.SlidingWindowSize))
  25. subscriber.SetOnDataMessageFn(func(m *mq_pb.SubscribeMessageResponse_Data) {
  26. executors.Execute(func() {
  27. record := &schema_pb.RecordValue{}
  28. err := proto.Unmarshal(m.Data.Value, record)
  29. if err != nil {
  30. glog.V(0).Infof("unmarshal record value: %v", err)
  31. if lastErr == nil {
  32. lastErr = err
  33. }
  34. return
  35. }
  36. if sendErr := stream.Send(&mq_agent_pb.SubscribeRecordResponse{
  37. Key: m.Data.Key,
  38. Value: record,
  39. TsNs: m.Data.TsNs,
  40. }); sendErr != nil {
  41. glog.V(0).Infof("send record: %v", sendErr)
  42. if lastErr == nil {
  43. lastErr = sendErr
  44. }
  45. }
  46. })
  47. })
  48. go func() {
  49. subErr := subscriber.Subscribe()
  50. if subErr != nil {
  51. glog.V(0).Infof("subscriber %s subscribe: %v", subscriber.SubscriberConfig.String(), subErr)
  52. if lastErr == nil {
  53. lastErr = subErr
  54. }
  55. }
  56. }()
  57. for {
  58. m, err := stream.Recv()
  59. if err != nil {
  60. glog.V(0).Infof("subscriber %d receive: %v", subscriber.SubscriberConfig.String(), err)
  61. return err
  62. }
  63. if m != nil {
  64. subscriber.PartitionOffsetChan <- sub_client.KeyedOffset{
  65. Key: m.AckKey,
  66. Offset: m.AckSequence,
  67. }
  68. }
  69. }
  70. }
  71. func (a *MessageQueueAgent) handleInitSubscribeRecordRequest(ctx context.Context, req *mq_agent_pb.SubscribeRecordRequest_InitSubscribeRecordRequest) *sub_client.TopicSubscriber {
  72. subscriberConfig := &sub_client.SubscriberConfiguration{
  73. ConsumerGroup: req.ConsumerGroup,
  74. ConsumerGroupInstanceId: req.ConsumerGroupInstanceId,
  75. GrpcDialOption: grpc.WithTransportCredentials(insecure.NewCredentials()),
  76. MaxPartitionCount: req.MaxSubscribedPartitions,
  77. SlidingWindowSize: req.SlidingWindowSize,
  78. }
  79. contentConfig := &sub_client.ContentConfiguration{
  80. Topic: topic.FromPbTopic(req.Topic),
  81. Filter: req.Filter,
  82. PartitionOffsets: req.PartitionOffsets,
  83. OffsetType: req.OffsetType,
  84. OffsetTsNs: req.OffsetTsNs,
  85. }
  86. topicSubscriber := sub_client.NewTopicSubscriber(
  87. ctx,
  88. a.brokersList(),
  89. subscriberConfig,
  90. contentConfig,
  91. make(chan sub_client.KeyedOffset, 1024),
  92. )
  93. return topicSubscriber
  94. }