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.
		
		
		
		
		
			
		
			
				
					
					
						
							205 lines
						
					
					
						
							5.5 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							205 lines
						
					
					
						
							5.5 KiB
						
					
					
				| package pub_balancer | |
| 
 | |
| import ( | |
| 	"fmt" | |
| 	cmap "github.com/orcaman/concurrent-map/v2" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/mq_pb" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/schema_pb" | |
| 	"github.com/stretchr/testify/assert" | |
| 	"testing" | |
| ) | |
| 
 | |
| func Test_allocateOneBroker(t *testing.T) { | |
| 	brokers := cmap.New[*BrokerStats]() | |
| 	brokers.SetIfAbsent("localhost:17777", &BrokerStats{ | |
| 		TopicPartitionCount: 0, | |
| 		CpuUsagePercent:     0, | |
| 	}) | |
| 
 | |
| 	tests := []struct { | |
| 		name            string | |
| 		args            args | |
| 		wantAssignments []*mq_pb.BrokerPartitionAssignment | |
| 	}{ | |
| 		{ | |
| 			name: "test only one broker", | |
| 			args: args{ | |
| 				brokers:        brokers, | |
| 				partitionCount: 1, | |
| 			}, | |
| 			wantAssignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 				{ | |
| 					LeaderBroker: "localhost:17777", | |
| 					Partition: &schema_pb.Partition{ | |
| 						RingSize:   MaxPartitionCount, | |
| 						RangeStart: 0, | |
| 						RangeStop:  MaxPartitionCount, | |
| 					}, | |
| 				}, | |
| 			}, | |
| 		}, | |
| 	} | |
| 	testThem(t, tests) | |
| } | |
| 
 | |
| type args struct { | |
| 	brokers        cmap.ConcurrentMap[string, *BrokerStats] | |
| 	partitionCount int32 | |
| } | |
| 
 | |
| func testThem(t *testing.T, tests []struct { | |
| 	name            string | |
| 	args            args | |
| 	wantAssignments []*mq_pb.BrokerPartitionAssignment | |
| }) { | |
| 	for _, tt := range tests { | |
| 		t.Run(tt.name, func(t *testing.T) { | |
| 			gotAssignments := AllocateTopicPartitions(tt.args.brokers, tt.args.partitionCount) | |
| 			assert.Equal(t, len(tt.wantAssignments), len(gotAssignments)) | |
| 			for i, gotAssignment := range gotAssignments { | |
| 				assert.Equal(t, tt.wantAssignments[i].LeaderBroker, gotAssignment.LeaderBroker) | |
| 				assert.Equal(t, tt.wantAssignments[i].Partition.RangeStart, gotAssignment.Partition.RangeStart) | |
| 				assert.Equal(t, tt.wantAssignments[i].Partition.RangeStop, gotAssignment.Partition.RangeStop) | |
| 				assert.Equal(t, tt.wantAssignments[i].Partition.RingSize, gotAssignment.Partition.RingSize) | |
| 			} | |
| 		}) | |
| 	} | |
| } | |
| 
 | |
| func TestEnsureAssignmentsToActiveBrokersX(t *testing.T) { | |
| 	type args struct { | |
| 		activeBrokers cmap.ConcurrentMap[string, *BrokerStats] | |
| 		followerCount int | |
| 		assignments   []*mq_pb.BrokerPartitionAssignment | |
| 	} | |
| 	activeBrokers := cmap.New[*BrokerStats]() | |
| 	activeBrokers.SetIfAbsent("localhost:1", &BrokerStats{}) | |
| 	activeBrokers.SetIfAbsent("localhost:2", &BrokerStats{}) | |
| 	activeBrokers.SetIfAbsent("localhost:3", &BrokerStats{}) | |
| 	activeBrokers.SetIfAbsent("localhost:4", &BrokerStats{}) | |
| 	activeBrokers.SetIfAbsent("localhost:5", &BrokerStats{}) | |
| 	activeBrokers.SetIfAbsent("localhost:6", &BrokerStats{}) | |
| 	lowActiveBrokers := cmap.New[*BrokerStats]() | |
| 	lowActiveBrokers.SetIfAbsent("localhost:1", &BrokerStats{}) | |
| 	lowActiveBrokers.SetIfAbsent("localhost:2", &BrokerStats{}) | |
| 	singleActiveBroker := cmap.New[*BrokerStats]() | |
| 	singleActiveBroker.SetIfAbsent("localhost:1", &BrokerStats{}) | |
| 	tests := []struct { | |
| 		name       string | |
| 		args       args | |
| 		hasChanges bool | |
| 	}{ | |
| 		{ | |
| 			name: "test empty leader", | |
| 			args: args{ | |
| 				activeBrokers: activeBrokers, | |
| 				followerCount: 1, | |
| 				assignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 					{ | |
| 						LeaderBroker:   "", | |
| 						Partition:      &schema_pb.Partition{}, | |
| 						FollowerBroker: "localhost:2", | |
| 					}, | |
| 				}, | |
| 			}, | |
| 			hasChanges: true, | |
| 		}, | |
| 		{ | |
| 			name: "test empty follower", | |
| 			args: args{ | |
| 				activeBrokers: activeBrokers, | |
| 				followerCount: 1, | |
| 				assignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 					{ | |
| 						LeaderBroker:   "localhost:1", | |
| 						Partition:      &schema_pb.Partition{}, | |
| 						FollowerBroker: "", | |
| 					}, | |
| 				}, | |
| 			}, | |
| 			hasChanges: true, | |
| 		}, | |
| 		{ | |
| 			name: "test dead follower", | |
| 			args: args{ | |
| 				activeBrokers: activeBrokers, | |
| 				followerCount: 1, | |
| 				assignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 					{ | |
| 						LeaderBroker:   "localhost:1", | |
| 						Partition:      &schema_pb.Partition{}, | |
| 						FollowerBroker: "localhost:200", | |
| 					}, | |
| 				}, | |
| 			}, | |
| 			hasChanges: true, | |
| 		}, | |
| 		{ | |
| 			name: "test dead leader and follower", | |
| 			args: args{ | |
| 				activeBrokers: activeBrokers, | |
| 				followerCount: 1, | |
| 				assignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 					{ | |
| 						LeaderBroker:   "localhost:100", | |
| 						Partition:      &schema_pb.Partition{}, | |
| 						FollowerBroker: "localhost:200", | |
| 					}, | |
| 				}, | |
| 			}, | |
| 			hasChanges: true, | |
| 		}, | |
| 		{ | |
| 			name: "test low active brokers", | |
| 			args: args{ | |
| 				activeBrokers: lowActiveBrokers, | |
| 				followerCount: 3, | |
| 				assignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 					{ | |
| 						LeaderBroker:   "localhost:1", | |
| 						Partition:      &schema_pb.Partition{}, | |
| 						FollowerBroker: "localhost:2", | |
| 					}, | |
| 				}, | |
| 			}, | |
| 			hasChanges: false, | |
| 		}, | |
| 		{ | |
| 			name: "test low active brokers with one follower", | |
| 			args: args{ | |
| 				activeBrokers: lowActiveBrokers, | |
| 				followerCount: 1, | |
| 				assignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 					{ | |
| 						LeaderBroker: "localhost:1", | |
| 						Partition:    &schema_pb.Partition{}, | |
| 					}, | |
| 				}, | |
| 			}, | |
| 			hasChanges: true, | |
| 		}, | |
| 		{ | |
| 			name: "test single active broker", | |
| 			args: args{ | |
| 				activeBrokers: singleActiveBroker, | |
| 				followerCount: 3, | |
| 				assignments: []*mq_pb.BrokerPartitionAssignment{ | |
| 					{ | |
| 						LeaderBroker:   "localhost:1", | |
| 						Partition:      &schema_pb.Partition{}, | |
| 						FollowerBroker: "localhost:2", | |
| 					}, | |
| 				}, | |
| 			}, | |
| 			hasChanges: true, | |
| 		}, | |
| 	} | |
| 	for _, tt := range tests { | |
| 		t.Run(tt.name, func(t *testing.T) { | |
| 			fmt.Printf("%v before %v\n", tt.name, tt.args.assignments) | |
| 			hasChanges := EnsureAssignmentsToActiveBrokers(tt.args.activeBrokers, tt.args.followerCount, tt.args.assignments) | |
| 			assert.Equalf(t, tt.hasChanges, hasChanges, "EnsureAssignmentsToActiveBrokers(%v, %v, %v)", tt.args.activeBrokers, tt.args.followerCount, tt.args.assignments) | |
| 			fmt.Printf("%v after %v\n", tt.name, tt.args.assignments) | |
| 		}) | |
| 	} | |
| }
 |