public static void GetAllSubjects(Config config) { var topicName = Guid.NewGuid().ToString(); var testSchema1 = "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"; var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig { SchemaRegistryUrl = config.Server }); var subjectsBefore = sr.GetAllSubjectsAsync().Result; var subject = sr.ConstructKeySubjectName(topicName); var id = sr.RegisterSchemaAsync(subject, testSchema1).Result; var subjectsAfter = sr.GetAllSubjectsAsync().Result; Assert.Equal(1, subjectsAfter.Count - subjectsBefore.Count); sr.RegisterSchemaAsync(subject, testSchema1).Wait(); var subjectsAfter2 = sr.GetAllSubjectsAsync().Result; Assert.Equal(subjectsAfter.Count, subjectsAfter2.Count); Assert.True(subjectsAfter2.Contains(subject)); }
public static void RegisterIncompatibleSchema(string server) { var topicName = Guid.NewGuid().ToString(); var testSchema1 = "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"; var sr = new CachedSchemaRegistryClient(new Dictionary <string, object> { { "schema.registry.url", server } }); var subject = sr.ConstructKeySubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User"); var id = sr.RegisterSchemaAsync(subject, testSchema1).Result; var testSchema2 = // incompatible with testSchema1 "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_shape\",\"type\":[\"string\",\"null\"]}]}"; Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result); Assert.Throws <AggregateException>(() => sr.RegisterSchemaAsync(subject, testSchema2).Result); Assert.True(sr.GetAllSubjectsAsync().Result.Contains(subject)); }
public static void GetId(Config config) { var topicName = Guid.NewGuid().ToString(); var testSchema1 = "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"; var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig { SchemaRegistryUrl = config.Server }); var subject = sr.ConstructKeySubjectName(topicName); var id = sr.RegisterSchemaAsync(subject, testSchema1).Result; var id2 = sr.GetSchemaIdAsync(subject, testSchema1).Result; Assert.Equal(id, id2); Assert.Throws <SchemaRegistryException>(() => { try { sr.GetSchemaIdAsync(subject, "{\"type\": \"string\"}").Wait(); } catch (AggregateException e) { throw e.InnerException; } }); }
public static void IsCompatible(string server) { var topicName = Guid.NewGuid().ToString(); var testSchema1 = "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"; var sr = new CachedSchemaRegistryClient(new Dictionary <string, object> { { "schema.registry.url", server } }); var subject = sr.ConstructKeySubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User"); var id = sr.RegisterSchemaAsync(subject, testSchema1).Result; var testSchema2 = // incompatible with testSchema1 "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_shape\",\"type\":[\"string\",\"null\"]}]}"; Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result); Assert.True(sr.IsCompatibleAsync(subject, testSchema1).Result); // Note: backwards / forwards compatibility scenarios are not tested here. This is really just testing the API call. }
public void ConstructKeySubjectName_Topic1() { var config = new SchemaRegistryConfig { Url = "irrelevanthost:8081" }; var src = new CachedSchemaRegistryClient(config); Assert.Equal("mytopic-key", src.ConstructKeySubjectName("mytopic", "myschemaname")); }
public void ConstructKeySubjectName() { var config = new Dictionary <string, object> { { "schema.registry.url", "irrelevanthost:8081" } }; CachedSchemaRegistryClient src = new CachedSchemaRegistryClient(config); Assert.Equal("mytopic-key", src.ConstructKeySubjectName("mytopic")); }
public void ConstructKeySubjectName_TopicRecord() { var config = new SchemaRegistryConfig { Url = "irrelevanthost:8081", KeySubjectNameStrategy = SubjectNameStrategy.TopicRecord }; var src = new CachedSchemaRegistryClient(config); Assert.Equal("mytopic-myschemaname", src.ConstructKeySubjectName("mytopic", "myschemaname")); }
public static void IsCompatible_Topic(Config config) { var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig { Url = config.Server }); var testSchema1 = "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"; var testSchema2 = // incompatible with testSchema1 "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_shape\",\"type\":[\"string\",\"null\"]}]}"; // case 1: record specified. var topicName = Guid.NewGuid().ToString(); var subject = sr.ConstructKeySubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User"); sr.RegisterSchemaAsync(subject, testSchema1).Wait(); Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result); Assert.True(sr.IsCompatibleAsync(subject, testSchema1).Result); // case 2: record not specified. topicName = Guid.NewGuid().ToString(); subject = sr.ConstructKeySubjectName(topicName); sr.RegisterSchemaAsync(subject, testSchema1).Wait(); Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result); Assert.True(sr.IsCompatibleAsync(subject, testSchema1).Result); // Note: backwards / forwards compatibility scenarios are not tested here. This is really just testing the API call. }
public static void Failover(Config config) { var testSchema = "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"; using (var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig { Url = $"{config.Server},http://localhost:65432" })) { var topicName = Guid.NewGuid().ToString(); var subject = sr.ConstructKeySubjectName(topicName); var id = sr.RegisterSchemaAsync(subject, testSchema).Result; var id2 = sr.GetSchemaIdAsync(subject, testSchema).Result; Assert.Equal(id, id2); } using (var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig { Url = $"http://localhost:65432,{config.Server}" })) { var topicName = Guid.NewGuid().ToString(); var subject = sr.ConstructKeySubjectName(topicName); var id = sr.RegisterSchemaAsync(subject, testSchema).Result; var id2 = sr.GetSchemaIdAsync(subject, testSchema).Result; Assert.Equal(id, id2); } using (var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig { Url = $"http://localhost:65432,http://localhost:65431" })) { var topicName = Guid.NewGuid().ToString(); var subject = sr.ConstructKeySubjectName(topicName); Assert.Throws <HttpRequestException>(() => { try { sr.RegisterSchemaAsync(subject, testSchema).Wait(); } catch (AggregateException e) { throw e.InnerException; } }); } }
public void ConstructKeySubjectName() { var config = new Dictionary <string, object> { { "schema.registry.url", "irrelevanthost:8081" } }; CachedSchemaRegistryClient src = new CachedSchemaRegistryClient(config); Assert.Equal("mytopic-key", src.ConstructKeySubjectName("mytopic", "myschemaname")); var configTopicName = new Dictionary <string, object> { { "schema.registry.url", "irrelevanthost:8081" }, { "schema.registry.subject.name.strategy", "topic_name_strategy" } }; CachedSchemaRegistryClient srcTopicName = new CachedSchemaRegistryClient(configTopicName); Assert.Equal("mytopic-key", srcTopicName.ConstructKeySubjectName("mytopic", "myschemaname")); var configRecordName = new Dictionary <string, object> { { "schema.registry.url", "irrelevanthost:8081" }, { "schema.registry.subject.name.strategy", "record_name_strategy" } }; CachedSchemaRegistryClient srcRecordName = new CachedSchemaRegistryClient(configRecordName); Assert.Equal("myschemaname", srcRecordName.ConstructKeySubjectName("mytopic", "myschemaname")); var configTopicRecordName = new Dictionary <string, object> { { "schema.registry.url", "irrelevanthost:8081" }, { "schema.registry.subject.name.strategy", "topic_record_name_strategy" } }; CachedSchemaRegistryClient srcTopicRecordName = new CachedSchemaRegistryClient(configTopicRecordName); Assert.Equal("mytopic-myschemaname", srcTopicRecordName.ConstructKeySubjectName("mytopic", "myschemaname")); }
public static void RegisterSameSchemaTwice(string server) { var topicName = Guid.NewGuid().ToString(); var testSchema1 = "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" + "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" + "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"; var sr = new CachedSchemaRegistryClient(new Dictionary <string, object> { { "schema.registry.url", server } }); var subject = sr.ConstructKeySubjectName(topicName); Assert.Equal(topicName + "-key", subject); var id1 = sr.RegisterSchemaAsync(subject, testSchema1).Result; var id2 = sr.RegisterSchemaAsync(subject, testSchema1).Result; Assert.Equal(id1, id2); Assert.True(sr.GetAllSubjectsAsync().Result.Contains(subject)); }
public static void RegularAndAvro(string bootstrapServers, string schemaRegistryServers) { using (var topic1 = new TemporaryTopic(bootstrapServers, 1)) using (var topic2 = new TemporaryTopic(bootstrapServers, 1)) { var producerConfig = new ProducerConfig { BootstrapServers = bootstrapServers }; var consumerConfig = new ConsumerConfig { BootstrapServers = bootstrapServers, GroupId = Guid.NewGuid().ToString(), SessionTimeoutMs = 6000, AutoOffsetReset = AutoOffsetReset.Earliest }; var schemaRegistryConfig = new SchemaRegistryConfig { SchemaRegistryUrl = schemaRegistryServers }; using (var schemaRegistry = new CachedSchemaRegistryClient(schemaRegistryConfig)) using (var producer = new ProducerBuilder <string, string>(producerConfig) .SetKeySerializer(Serializers.Utf8) .SetValueSerializer(new AvroSerializer <string>(schemaRegistry)) .Build()) { // implicit check that this does not fail. producer.ProduceAsync(topic1.Name, new Message <string, string> { Key = "hello", Value = "world" }).Wait(); // check that the value type was registered with SR, and the key was not. Assert.Throws <SchemaRegistryException>(() => { try { schemaRegistry.GetLatestSchemaAsync(schemaRegistry.ConstructKeySubjectName(topic1.Name)).Wait(); } catch (AggregateException e) { throw e.InnerException; } }); var s2 = schemaRegistry.GetLatestSchemaAsync(schemaRegistry.ConstructValueSubjectName(topic1.Name)).Result; } using (var schemaRegistry = new CachedSchemaRegistryClient(schemaRegistryConfig)) using (var producer = new ProducerBuilder <string, string>(producerConfig) .SetKeySerializer(new AvroSerializer <string>(schemaRegistry)) .SetValueSerializer(Serializers.Utf8) .Build()) { // implicit check that this does not fail. producer.ProduceAsync(topic2.Name, new Message <string, string> { Key = "hello", Value = "world" }).Wait(); // check that the key type was registered with SR, and the value was not. Assert.Throws <SchemaRegistryException>(() => { try { schemaRegistry.GetLatestSchemaAsync(schemaRegistry.ConstructValueSubjectName(topic2.Name)).Wait(); } catch (AggregateException e) { throw e.InnerException; } }); var s2 = schemaRegistry.GetLatestSchemaAsync(schemaRegistry.ConstructKeySubjectName(topic2.Name)).Result; } // check the above can be consumed (using regular / Avro serializers as appropriate) using (var schemaRegistry = new CachedSchemaRegistryClient(schemaRegistryConfig)) { using (var consumer = new ConsumerBuilder <string, string>(consumerConfig) .SetKeyDeserializer(Deserializers.Utf8) .SetValueDeserializer(new AvroDeserializer <string>(schemaRegistry)) .Build()) { consumer.Assign(new TopicPartitionOffset(topic1.Name, 0, 0)); var cr = consumer.Consume(); Assert.Equal("hello", cr.Key); Assert.Equal("world", cr.Value); } using (var consumer = new ConsumerBuilder <string, string>(consumerConfig) .SetKeyDeserializer(new AvroDeserializer <string>(schemaRegistry)) .SetValueDeserializer(Deserializers.Utf8).Build()) { consumer.Assign(new TopicPartitionOffset(topic2.Name, 0, 0)); var cr = consumer.Consume(); Assert.Equal("hello", cr.Key); Assert.Equal("world", cr.Value); } using (var consumer = new ConsumerBuilder <string, string>(consumerConfig) .SetKeyDeserializer(Deserializers.Utf8) .SetValueDeserializer(new AvroDeserializer <string>(schemaRegistry)) .Build()) { consumer.Assign(new TopicPartitionOffset(topic2.Name, 0, 0)); Assert.ThrowsAny <ConsumeException>(() => { try { consumer.Consume(); } catch (AggregateException e) { throw e.InnerException; } }); } using (var consumer = new ConsumerBuilder <string, string>(consumerConfig) .SetKeyDeserializer(new AvroDeserializer <string>(schemaRegistry)) .SetValueDeserializer(Deserializers.Utf8) .Build()) { consumer.Assign(new TopicPartitionOffset(topic1.Name, 0, 0)); Assert.ThrowsAny <ConsumeException>(() => { try { consumer.Consume(); } catch (AggregateException e) { throw e.InnerException; } }); } } } }