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.

113 lines
2.6 KiB

5 years ago
5 years ago
  1. package client
  2. import (
  3. "context"
  4. "github.com/OneOfOne/xxhash"
  5. "github.com/chrislusf/seaweedfs/weed/pb/messaging_pb"
  6. )
  7. type Publisher struct {
  8. publishClients []messaging_pb.SeaweedMessaging_PublishClient
  9. topicConfiguration *messaging_pb.TopicConfiguration
  10. messageCount uint64
  11. publisherId string
  12. }
  13. func (mc *MessagingClient) NewPublisher(publisherId, namespace, topic string) (*Publisher, error) {
  14. // read topic configuration
  15. topicConfiguration := &messaging_pb.TopicConfiguration{
  16. PartitionCount: 4,
  17. }
  18. publishClients := make([]messaging_pb.SeaweedMessaging_PublishClient, topicConfiguration.PartitionCount)
  19. for i := 0; i < int(topicConfiguration.PartitionCount); i++ {
  20. client, err := mc.setupPublisherClient(namespace, topic, int32(i))
  21. if err != nil {
  22. return nil, err
  23. }
  24. publishClients[i] = client
  25. }
  26. return &Publisher{
  27. publishClients: publishClients,
  28. topicConfiguration: topicConfiguration,
  29. }, nil
  30. }
  31. func (mc *MessagingClient) setupPublisherClient(namespace, topic string, partition int32) (messaging_pb.SeaweedMessaging_PublishClient, error) {
  32. stream, err := messaging_pb.NewSeaweedMessagingClient(mc.grpcConnection).Publish(context.Background())
  33. if err != nil {
  34. return nil, err
  35. }
  36. // send init message
  37. err = stream.Send(&messaging_pb.PublishRequest{
  38. Init: &messaging_pb.PublishRequest_InitMessage{
  39. Namespace: namespace,
  40. Topic: topic,
  41. Partition: partition,
  42. },
  43. })
  44. if err != nil {
  45. return nil, err
  46. }
  47. // process init response
  48. initResponse, err := stream.Recv()
  49. if err != nil {
  50. return nil, err
  51. }
  52. if initResponse.Redirect != nil {
  53. // TODO follow redirection
  54. }
  55. if initResponse.Config != nil {
  56. }
  57. // setup looks for control messages
  58. doneChan := make(chan error, 1)
  59. go func() {
  60. for {
  61. in, err := stream.Recv()
  62. if err != nil {
  63. doneChan <- err
  64. return
  65. }
  66. if in.Redirect != nil {
  67. }
  68. if in.Config != nil {
  69. }
  70. }
  71. }()
  72. return stream, nil
  73. }
  74. func (p *Publisher) Publish(m *messaging_pb.Message) error {
  75. hashValue := p.messageCount
  76. p.messageCount++
  77. if p.topicConfiguration.Partitoning == messaging_pb.TopicConfiguration_NonNullKeyHash {
  78. if m.Key != nil {
  79. hashValue = xxhash.Checksum64(m.Key)
  80. }
  81. } else if p.topicConfiguration.Partitoning == messaging_pb.TopicConfiguration_KeyHash {
  82. hashValue = xxhash.Checksum64(m.Key)
  83. } else {
  84. // round robin
  85. }
  86. idx := int(hashValue) % len(p.publishClients)
  87. if idx < 0 {
  88. idx += len(p.publishClients)
  89. }
  90. return p.publishClients[idx].Send(&messaging_pb.PublishRequest{
  91. Data: m,
  92. })
  93. }
  94. func (p *Publisher) Shutdown() {
  95. for _, client := range p.publishClients {
  96. client.CloseSend()
  97. }
  98. }