broker_grpc_configure.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package broker
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/seaweedfs/seaweedfs/weed/mq/pub_balancer"
  6. "github.com/seaweedfs/seaweedfs/weed/mq/topic"
  7. "github.com/seaweedfs/seaweedfs/weed/pb"
  8. "github.com/seaweedfs/seaweedfs/weed/pb/mq_pb"
  9. "google.golang.org/grpc/codes"
  10. "google.golang.org/grpc/status"
  11. )
  12. // ConfigureTopic Runs on any broker, but proxied to the balancer if not the balancer
  13. // It generates an assignments based on existing allocations,
  14. // and then assign the partitions to the brokers.
  15. func (b *MessageQueueBroker) ConfigureTopic(ctx context.Context, request *mq_pb.ConfigureTopicRequest) (resp *mq_pb.ConfigureTopicResponse, err error) {
  16. if b.currentBalancer == "" {
  17. return nil, status.Errorf(codes.Unavailable, "no balancer")
  18. }
  19. if !b.lockAsBalancer.IsLocked() {
  20. proxyErr := b.withBrokerClient(false, b.currentBalancer, func(client mq_pb.SeaweedMessagingClient) error {
  21. resp, err = client.ConfigureTopic(ctx, request)
  22. return nil
  23. })
  24. if proxyErr != nil {
  25. return nil, proxyErr
  26. }
  27. return resp, err
  28. }
  29. ret := &mq_pb.ConfigureTopicResponse{}
  30. ret.BrokerPartitionAssignments, err = b.Balancer.LookupOrAllocateTopicPartitions(request.Topic, true, request.PartitionCount)
  31. for _, bpa := range ret.BrokerPartitionAssignments {
  32. // fmt.Printf("create topic %s on %s\n", request.Topic, bpa.LeaderBroker)
  33. if doCreateErr := b.withBrokerClient(false, pb.ServerAddress(bpa.LeaderBroker), func(client mq_pb.SeaweedMessagingClient) error {
  34. _, doCreateErr := client.AssignTopicPartitions(ctx, &mq_pb.AssignTopicPartitionsRequest{
  35. Topic: request.Topic,
  36. BrokerPartitionAssignments: []*mq_pb.BrokerPartitionAssignment{
  37. {
  38. Partition: bpa.Partition,
  39. },
  40. },
  41. IsLeader: true,
  42. IsDraining: false,
  43. })
  44. if doCreateErr != nil {
  45. return fmt.Errorf("do create topic %s on %s: %v", request.Topic, bpa.LeaderBroker, doCreateErr)
  46. }
  47. brokerStats, found := b.Balancer.Brokers.Get(bpa.LeaderBroker)
  48. if !found {
  49. brokerStats = pub_balancer.NewBrokerStats()
  50. if !b.Balancer.Brokers.SetIfAbsent(bpa.LeaderBroker, brokerStats) {
  51. brokerStats, _ = b.Balancer.Brokers.Get(bpa.LeaderBroker)
  52. }
  53. }
  54. brokerStats.RegisterAssignment(request.Topic, bpa.Partition)
  55. return nil
  56. }); doCreateErr != nil {
  57. return nil, doCreateErr
  58. }
  59. }
  60. // TODO revert if some error happens in the middle of the assignments
  61. return ret, err
  62. }
  63. // AssignTopicPartitions Runs on the assigned broker, to execute the topic partition assignment
  64. func (b *MessageQueueBroker) AssignTopicPartitions(c context.Context, request *mq_pb.AssignTopicPartitionsRequest) (*mq_pb.AssignTopicPartitionsResponse, error) {
  65. ret := &mq_pb.AssignTopicPartitionsResponse{}
  66. self := pb.ServerAddress(fmt.Sprintf("%s:%d", b.option.Ip, b.option.Port))
  67. // drain existing topic partition subscriptions
  68. for _, brokerPartition := range request.BrokerPartitionAssignments {
  69. localPartition := topic.FromPbBrokerPartitionAssignment(self, brokerPartition)
  70. if request.IsDraining {
  71. // TODO drain existing topic partition subscriptions
  72. b.localTopicManager.RemoveTopicPartition(
  73. topic.FromPbTopic(request.Topic),
  74. localPartition.Partition)
  75. } else {
  76. b.localTopicManager.AddTopicPartition(
  77. topic.FromPbTopic(request.Topic),
  78. localPartition)
  79. }
  80. }
  81. // if is leader, notify the followers to drain existing topic partition subscriptions
  82. if request.IsLeader {
  83. for _, brokerPartition := range request.BrokerPartitionAssignments {
  84. for _, follower := range brokerPartition.FollowerBrokers {
  85. err := pb.WithBrokerGrpcClient(false, follower, b.grpcDialOption, func(client mq_pb.SeaweedMessagingClient) error {
  86. _, err := client.AssignTopicPartitions(context.Background(), request)
  87. return err
  88. })
  89. if err != nil {
  90. return ret, err
  91. }
  92. }
  93. }
  94. }
  95. return ret, nil
  96. }