public void Producer_CustomPartitioner(string bootstrapServers) { LogToFile("start Producer_CustomPartitioner"); const int PARTITION_COUNT = 42; var producerConfig = new ProducerConfig { BootstrapServers = bootstrapServers, }; for (int j = 0; j < 3; ++j) { using (var topic = new TemporaryTopic(bootstrapServers, PARTITION_COUNT)) { Action <DeliveryReport <string, string> > dh = (DeliveryReport <string, string> dr) => { Assert.StartsWith($"test key ", dr.Message.Key); Assert.StartsWith($"test val ", dr.Message.Value); var expectedPartition = int.Parse(dr.Message.Key.Split(" ").Last()); Assert.Equal(ErrorCode.NoError, dr.Error.Code); Assert.Equal(PersistenceStatus.Persisted, dr.Status); Assert.Equal(topic.Name, dr.Topic); Assert.Equal(expectedPartition, (int)dr.Partition); Assert.True(dr.Offset >= 0); Assert.Equal(TimestampType.CreateTime, dr.Message.Timestamp.Type); Assert.True(Math.Abs((DateTime.UtcNow - dr.Message.Timestamp.UtcDateTime).TotalMinutes) < 1.0); }; ProducerBuilder <string, string> producerBuilder = null; switch (j) { case 0: // Topic level custom partitioner. producerBuilder = new ProducerBuilder <string, string>(producerConfig); producerBuilder.SetPartitioner(topic.Name, (string topicName, int partitionCount, ReadOnlySpan <byte> keyData, bool keyIsNull) => { Assert.Equal(topic.Name, topicName); var keyString = System.Text.UTF8Encoding.UTF8.GetString(keyData.ToArray()); return(int.Parse(keyString.Split(" ").Last()) % partitionCount); }); break; case 1: // Default custom partitioner producerBuilder = new ProducerBuilder <string, string>(producerConfig); producerBuilder.SetDefaultPartitioner((string topicName, int partitionCount, ReadOnlySpan <byte> keyData, bool keyIsNull) => { Assert.Equal(topic.Name, topicName); var keyString = System.Text.UTF8Encoding.UTF8.GetString(keyData.ToArray()); return(int.Parse(keyString.Split(" ").Last()) % partitionCount); }); break; case 2: // Default custom partitioner in case where default topic config is present due to topic level config in top-level config. var producerConfig2 = new ProducerConfig { BootstrapServers = bootstrapServers, MessageTimeoutMs = 10000 }; producerBuilder = new ProducerBuilder <string, string>(producerConfig2); producerBuilder.SetDefaultPartitioner((string topicName, int partitionCount, ReadOnlySpan <byte> keyData, bool keyIsNull) => { Assert.Equal(topic.Name, topicName); var keyString = System.Text.UTF8Encoding.UTF8.GetString(keyData.ToArray()); return(int.Parse(keyString.Split(" ").Last()) % partitionCount); }); break; default: Assert.True(false); break; } using (var producer = producerBuilder.Build()) { for (int i = 0; i < PARTITION_COUNT; ++i) { producer.Produce( topic.Name, new Message <string, string> { Key = $"test key {i}", Value = $"test val {i}" }, dh); } producer.Flush(TimeSpan.FromSeconds(10)); } } } // Null key using (var topic = new TemporaryTopic(bootstrapServers, PARTITION_COUNT)) using (var producer = new ProducerBuilder <Null, string>(producerConfig) .SetDefaultPartitioner((string topicName, int partitionCount, ReadOnlySpan <byte> keyData, bool keyIsNull) => { Assert.True(keyIsNull); return(0); }) .Build()) { producer.Produce(topic.Name, new Message <Null, string> { Value = "test value" }); producer.Flush(TimeSpan.FromSeconds(10)); } Assert.Equal(0, Library.HandleCount); LogToFile("end Producer_CustomPartitioner"); }