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.

91 lines
2.3 KiB

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