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.

100 lines
2.6 KiB

5 years ago
5 years ago
  1. package msgclient
  2. import (
  3. "context"
  4. "io"
  5. "time"
  6. "github.com/chrislusf/seaweedfs/weed/messaging/broker"
  7. "github.com/chrislusf/seaweedfs/weed/pb/messaging_pb"
  8. "google.golang.org/grpc"
  9. )
  10. type Subscriber struct {
  11. subscriberClients []messaging_pb.SeaweedMessaging_SubscribeClient
  12. subscriberId string
  13. }
  14. func (mc *MessagingClient) NewSubscriber(subscriberId, namespace, topic string, partitionId int, startTime time.Time) (*Subscriber, error) {
  15. // read topic configuration
  16. topicConfiguration := &messaging_pb.TopicConfiguration{
  17. PartitionCount: 4,
  18. }
  19. subscriberClients := make([]messaging_pb.SeaweedMessaging_SubscribeClient, topicConfiguration.PartitionCount)
  20. for i := 0; i < int(topicConfiguration.PartitionCount); i++ {
  21. if partitionId>=0 && i != partitionId {
  22. continue
  23. }
  24. tp := broker.TopicPartition{
  25. Namespace: namespace,
  26. Topic: topic,
  27. Partition: int32(i),
  28. }
  29. grpcClientConn, err := mc.findBroker(tp)
  30. if err != nil {
  31. return nil, err
  32. }
  33. client, err := setupSubscriberClient(grpcClientConn, tp, subscriberId, startTime)
  34. if err != nil {
  35. return nil, err
  36. }
  37. subscriberClients[i] = client
  38. }
  39. return &Subscriber{
  40. subscriberClients: subscriberClients,
  41. subscriberId: subscriberId,
  42. }, nil
  43. }
  44. func setupSubscriberClient(grpcConnection *grpc.ClientConn, tp broker.TopicPartition, subscriberId string, startTime time.Time) (stream messaging_pb.SeaweedMessaging_SubscribeClient, err error) {
  45. stream, err = messaging_pb.NewSeaweedMessagingClient(grpcConnection).Subscribe(context.Background())
  46. if err != nil {
  47. return
  48. }
  49. // send init message
  50. err = stream.Send(&messaging_pb.SubscriberMessage{
  51. Init: &messaging_pb.SubscriberMessage_InitMessage{
  52. Namespace: tp.Namespace,
  53. Topic: tp.Topic,
  54. Partition: tp.Partition,
  55. StartPosition: messaging_pb.SubscriberMessage_InitMessage_TIMESTAMP,
  56. TimestampNs: startTime.UnixNano(),
  57. SubscriberId: subscriberId,
  58. },
  59. })
  60. if err != nil {
  61. return
  62. }
  63. return stream, nil
  64. }
  65. func doSubscribe(subscriberClient messaging_pb.SeaweedMessaging_SubscribeClient, processFn func(m *messaging_pb.Message)) error {
  66. for {
  67. resp, listenErr := subscriberClient.Recv()
  68. if listenErr == io.EOF {
  69. return nil
  70. }
  71. if listenErr != nil {
  72. println(listenErr.Error())
  73. return listenErr
  74. }
  75. if resp.Data == nil {
  76. // this could be heartbeat from broker
  77. continue
  78. }
  79. processFn(resp.Data)
  80. }
  81. }
  82. // Subscribe starts goroutines to process the messages
  83. func (s *Subscriber) Subscribe(processFn func(m *messaging_pb.Message)) {
  84. for i := 0; i < len(s.subscriberClients); i++ {
  85. if s.subscriberClients[i] != nil {
  86. go doSubscribe(s.subscriberClients[i], processFn)
  87. }
  88. }
  89. }