diff --git a/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md b/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md index 7d9bfaec4a3c..971cc7e451a2 100644 --- a/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md +++ b/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## 1.0.0 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 1.0.0-beta.7 (2022-03-10) ### Breaking Changes diff --git a/sdk/schemaregistry/schema-registry-avro/package.json b/sdk/schemaregistry/schema-registry-avro/package.json index 6db6f0ed36a8..81696358d9f3 100644 --- a/sdk/schemaregistry/schema-registry-avro/package.json +++ b/sdk/schemaregistry/schema-registry-avro/package.json @@ -1,6 +1,6 @@ { "name": "@azure/schema-registry-avro", - "version": "1.0.0-beta.7", + "version": "1.0.0", "description": "Schema Registry Avro Serializer Library with typescript type definitions for node.js and browser.", "sdk-type": "client", "main": "dist/index.js", @@ -80,7 +80,7 @@ "devDependencies": { "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", - "@azure/event-hubs": "^5.8.0-beta.1", + "@azure/event-hubs": "^5.8.0-beta.2", "@azure/identity": "^2.0.1", "@azure/test-utils": "^1.0.0", "@azure-tools/test-recorder": "^1.0.0", diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/README.md b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/README.md similarity index 50% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/README.md rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/README.md index 0c724a685ec8..5d032fa44327 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/README.md +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/README.md @@ -1,10 +1,13 @@ -# Azure Schema Registry client library samples for JavaScript +# Azure Schema Registry client library samples for JavaScript (Beta) These sample programs show how to use the JavaScript client libraries for Azure Schema Registry in some common scenarios. -| **File Name** | **Description** | -| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -| [schemaRegistryAvroSample.js][schemaregistryavrosample] | Demonstrates the use of SchemaRegistryAvroSerializer to serialize and deserialize using schema from Schema Registry. | +| **File Name** | **Description** | +| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [schemaRegistryAvroSample.js][schemaregistryavrosample] | Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry. | +| [withEventHubsBufferedProducerClient.js][witheventhubsbufferedproducerclient] | Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Buffered Producer Client. | +| [withEventHubsConsumerClient.js][witheventhubsconsumerclient] | Demonstrates the use of AvroSerializer to deserialize messages with avro-serialized payload received from the Event Hub Consumer Client. | +| [withEventHubsProducerClient.js][witheventhubsproducerclient] | Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Producer Client. | ## Prerequisites @@ -46,7 +49,10 @@ npx cross-env SCHEMA_REGISTRY_ENDPOINT="" SCHEMA_REGIS Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients. -[schemaregistryavrosample]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/schemaRegistryAvroSample.js +[schemaregistryavrosample]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/schemaRegistryAvroSample.js +[witheventhubsbufferedproducerclient]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsBufferedProducerClient.js +[witheventhubsconsumerclient]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsConsumerClient.js +[witheventhubsproducerclient]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsProducerClient.js [apiref]: https://docs.microsoft.com/javascript/api/@azure/schema-registry-avro [freesub]: https://azure.microsoft.com/free/ [createinstance_azureschemaregistryresource]: https://aka.ms/schemaregistry diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/package.json b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/package.json similarity index 82% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/package.json rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/package.json index 5ed84abc59b8..b0235d206ec2 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/package.json +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/package.json @@ -1,8 +1,8 @@ { - "name": "azure-schema-registry-avro-samples-js", + "name": "azure-schema-registry-avro-samples-js-beta", "private": true, "version": "1.0.0", - "description": "Azure Schema Registry client library samples for JavaScript", + "description": "Azure Schema Registry client library samples for JavaScript (Beta)", "engines": { "node": ">=12.0.0" }, @@ -26,6 +26,7 @@ "@azure/schema-registry-avro": "next", "dotenv": "latest", "@azure/identity": "^2.0.1", - "@azure/schema-registry": "1.0.1" + "@azure/schema-registry": "1.0.2", + "@azure/event-hubs": "^5.8.0-beta.1" } } diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/sample.env b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/sample.env similarity index 55% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/sample.env rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/sample.env index 18e56c11ef2f..15f5a8fc6249 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/sample.env +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/sample.env @@ -9,3 +9,12 @@ SCHEMA_REGISTRY_GROUP= AZURE_TENANT_ID= AZURE_CLIENT_ID= AZURE_CLIENT_SECRET= + +# Used in samples that use Event Hubs. Retrieve these values from an Event Hub in the Azure portal. +EVENTHUB_CONNECTION_STRING= +EVENTHUB_NAME= +CONSUMER_GROUP_NAME= + +# Used in samples that use Event Grid. Retrieve these values from an Event Grid topic in the Azure portal +EVENT_GRID_TOPIC_ENDPOINT= +EVENT_GRID_TOPIC_API_KEY= \ No newline at end of file diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/schemaRegistryAvroSample.js b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/schemaRegistryAvroSample.js new file mode 100644 index 000000000000..0bee4a39f3f8 --- /dev/null +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/schemaRegistryAvroSample.js @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @summary Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry. + */ + +const { DefaultAzureCredential } = require("@azure/identity"); +const { SchemaRegistryClient } = require("@azure/schema-registry"); +const { AvroSerializer } = require("@azure/schema-registry-avro"); + +// Load the .env file if it exists +require("dotenv").config(); + +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup +const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; + +// Sample Avro Schema for user with first and last names +const schemaObject = { + type: "record", + name: "User", + namespace: "com.azure.schemaregistry.samples", + fields: [ + { + name: "firstName", + type: "string", + }, + { + name: "lastName", + type: "string", + }, + ], +}; + +const schema = JSON.stringify(schemaObject); + +// Description of the schema for registration +const schemaDescription = { + name: `${schemaObject.namespace}.${schemaObject.name}`, + groupName, + format: "Avro", + definition: schema, +}; + +async function main() { + // Create a new client + const client = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); + + // Register the schema. This would generally have been done somewhere else. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. + await client.registerSchema(schemaDescription); + + // Create a new serializer backed by the client + const serializer = new AvroSerializer(client, { groupName }); + + // serialize an object that matches the schema and put it in a message + const value = { firstName: "Jane", lastName: "Doe" }; + const message = await serializer.serializeMessageData(value, schema); + console.log("Created message:"); + console.log(JSON.stringify(message)); + + // deserialize the message back to an object + const deserializedObject = await serializer.deserializeMessageData(message); + console.log("Deserialized object:"); + console.log(JSON.stringify(deserializedObject)); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); + +module.exports = { main }; diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsBufferedProducerClient.js b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsBufferedProducerClient.js new file mode 100644 index 000000000000..28ec406483b5 --- /dev/null +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsBufferedProducerClient.js @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @summary Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Buffered Producer Client. + */ + +const { DefaultAzureCredential } = require("@azure/identity"); +const { SchemaRegistryClient } = require("@azure/schema-registry"); +const { AvroSerializer } = require("@azure/schema-registry-avro"); +const { EventHubBufferedProducerClient, createEventDataAdapter } = require("@azure/event-hubs"); + +// Load the .env file if it exists +require("dotenv").config(); + +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup +const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; + +// The connection string for Event Hubs +const eventHubsConnectionString = process.env["EVENTHUB_CONNECTION_STRING"] || ""; + +// Sample Avro Schema for user with first and last names +const schemaObject = { + type: "record", + name: "User", + namespace: "com.azure.schemaregistry.samples", + fields: [ + { + name: "firstName", + type: "string", + }, + { + name: "lastName", + type: "string", + }, + ], +}; + +const schema = JSON.stringify(schemaObject); + +// Description of the schema for registration +const schemaDescription = { + name: `${schemaObject.namespace}.${schemaObject.name}`, + groupName, + format: "Avro", + definition: schema, +}; + +async function handleError() { + console.log("An error occured when sending a message"); +} + +async function main() { + // Create a new client + const schemaRegistryClient = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); + + // Register the schema. This would generally have been done somewhere else. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. + await schemaRegistryClient.registerSchema(schemaDescription); + + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { + groupName, + messageAdapter: createEventDataAdapter(), + }); + + const eventHubsBufferedProducerClient = new EventHubBufferedProducerClient( + eventHubsConnectionString, + { + onSendEventsErrorHandler: handleError, + } + ); + + // serialize an object that matches the schema + const value = { firstName: "Jane", lastName: "Doe" }; + const message = await serializer.serializeMessageData(value, schema); + console.log("Created message:"); + console.log(message); + + await eventHubsBufferedProducerClient.enqueueEvent(message); + console.log(`Message was added to the queue and is about to be sent`); + + // Wait for a bit before cleaning up the sample + setTimeout(async () => { + await eventHubsBufferedProducerClient.close({ flush: true }); + console.log(`Exiting sample`); + }, 30 * 1000); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); + +module.exports = { main }; diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsConsumerClient.js b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsConsumerClient.js new file mode 100644 index 000000000000..5a0b8fa811a1 --- /dev/null +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsConsumerClient.js @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @summary Demonstrates the use of AvroSerializer to deserialize messages with avro-serialized payload received from the Event Hub Consumer Client. + */ + +const { DefaultAzureCredential } = require("@azure/identity"); +const { SchemaRegistryClient } = require("@azure/schema-registry"); +const { AvroSerializer } = require("@azure/schema-registry-avro"); +const { + EventHubConsumerClient, + earliestEventPosition, + createEventDataAdapter, +} = require("@azure/event-hubs"); + +// Load the .env file if it exists +require("dotenv").config(); + +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup +const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; + +// The connection string for Event Hubs +const eventHubsConnectionString = process.env["EVENTHUB_CONNECTION_STRING"] || ""; + +// The name of Event Hub the client will connect to +const eventHubName = process.env["EVENTHUB_NAME"] || ""; + +// The name of the Event Hub consumer group from which you want to process events +const consumerGroup = process.env["CONSUMER_GROUP_NAME"] || ""; + +// Sample Avro Schema for user with first and last names +const schemaObject = { + type: "record", + name: "User", + namespace: "com.azure.schemaregistry.samples", + fields: [ + { + name: "firstName", + type: "string", + }, + { + name: "lastName", + type: "string", + }, + ], +}; + +const schema = JSON.stringify(schemaObject); + +// Description of the schema for registration +const schemaDescription = { + name: `${schemaObject.namespace}.${schemaObject.name}`, + groupName, + format: "Avro", + definition: schema, +}; + +async function main() { + // Create a new client + const schemaRegistryClient = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); + + // Register the schema. This would generally have been done somewhere else. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. + await schemaRegistryClient.registerSchema(schemaDescription); + + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { + groupName, + messageAdapter: createEventDataAdapter(), + }); + + const eventHubConsumerClient = new EventHubConsumerClient( + consumerGroup, + eventHubsConnectionString, + eventHubName + ); + + const subscription = eventHubConsumerClient.subscribe( + { + // The callback where you add your code to process incoming events + processEvents: async (events, context) => { + // Note: It is possible for `events` to be an empty array. + // This can happen if there were no new events to receive + // in the `maxWaitTimeInSeconds`, which is defaulted to + // 60 seconds. + // The `maxWaitTimeInSeconds` can be changed by setting + // it in the `options` passed to `subscribe()`. + for (const event of events) { + console.log( + `Received event: '${JSON.stringify(event)}' from partition: '${ + context.partitionId + }' and consumer group: '${context.consumerGroup}'` + ); + if (event.contentType !== undefined && event.body) { + const contentTypeParts = event.contentType.split("+"); + if (contentTypeParts[0] === "avro/binary") { + const deserializedEvent = await serializer.deserializeMessageData(event); + console.log(`Deserialized message: '${JSON.stringify(deserializedEvent)}'`); + } + } + } + }, + processError: async (err, context) => { + console.log(`Error on partition "${context.partitionId}": ${err}`); + }, + }, + { startPosition: earliestEventPosition } + ); + + // Wait for a bit before cleaning up the sample + setTimeout(async () => { + await subscription.close(); + await eventHubConsumerClient.close(); + console.log(`Exiting sample`); + }, 30 * 1000); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); + +module.exports = { main }; diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsProducerClient.js b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsProducerClient.js new file mode 100644 index 000000000000..323e1dadf385 --- /dev/null +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/javascript/withEventHubsProducerClient.js @@ -0,0 +1,170 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @summary Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Producer Client. + */ + +const { DefaultAzureCredential } = require("@azure/identity"); +const { SchemaRegistryClient } = require("@azure/schema-registry"); +const { AvroSerializer } = require("@azure/schema-registry-avro"); +const { EventHubProducerClient, createEventDataAdapter } = require("@azure/event-hubs"); + +// Load the .env file if it exists +require("dotenv").config(); + +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup +const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; + +// The connection string for Event Hubs +const eventHubsConnectionString = process.env["EVENTHUB_CONNECTION_STRING"] || ""; + +// The name of Event Hub the client will connect to +const eventHubName = process.env["EVENTHUB_NAME"] || ""; + +// Sample Avro Schema for user with first and last names +const schemaObject = { + type: "record", + name: "User", + namespace: "com.azure.schemaregistry.samples", + fields: [ + { + name: "firstName", + type: "string", + }, + { + name: "lastName", + type: "string", + }, + ], +}; + +const schema = JSON.stringify(schemaObject); + +// Description of the schema for registration +const schemaDescription = { + name: `${schemaObject.namespace}.${schemaObject.name}`, + groupName, + format: "Avro", + definition: schema, +}; + +async function main() { + // Create a new client + const schemaRegistryClient = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); + + // Register the schema. This would generally have been done somewhere else. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. + await schemaRegistryClient.registerSchema(schemaDescription); + + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { + groupName, + messageAdapter: createEventDataAdapter(), + }); + + const eventHubsProducerClient = new EventHubProducerClient( + eventHubsConnectionString, + eventHubName + ); + + // serialize an object that matches the schema + const value = { firstName: "Joe", lastName: "Doe" }; + const message = await serializer.serializeMessageData(value, schema); + console.log("Created message:"); + console.log(message); + + const eventsToSend = [message]; + + // By not specifying a partition ID or a partition key we allow the server to choose + // which partition will accept this message. + // + // This pattern works well if the consumers of your events do not have any particular + // requirements about the ordering of batches against other batches or if you don't care + // which messages are assigned to which partition. + // + // If you would like more control you can pass either a `partitionKey` or a `partitionId` + // into the createBatch() `options` parameter which will allow you full control over the + // destination. + const batchOptions = { + // The maxSizeInBytes lets you manually control the size of the batch. + // if this is not set we will get the maximum batch size from Event Hubs. + // + // For this sample you can change the batch size to see how different parts + // of the sample handle batching. In production we recommend using the default + // and not specifying a maximum size. + // + // maxSizeInBytes: 200 + }; + + let batch = await eventHubsProducerClient.createBatch(batchOptions); + + let numEventsSent = 0; + + // add events to our batch + let i = 0; + + while (i < eventsToSend.length) { + // messages can fail to be added to the batch if they exceed the maximum size configured for + // the EventHub. + const isAdded = batch.tryAdd(eventsToSend[i]); + + if (isAdded) { + console.log(`Added a message with index ${i} to the batch`); + ++i; + continue; + } + + if (batch.count === 0) { + // If we can't add it and the batch is empty that means the message we're trying to send + // is too large, even when it would be the _only_ message in the batch. + // + // At this point you'll need to decide if you're okay with skipping this message entirely + // or find some way to shrink it. + console.log(`Message was too large and can't be sent until it's made smaller. Skipping...`); + ++i; + continue; + } + + // otherwise this just signals a good spot to send our batch + console.log(`Batch is full - sending ${batch.count} messages as a single batch.`); + await eventHubsProducerClient.sendBatch(batch); + numEventsSent += batch.count; + + // and create a new one to house the next set of messages + batch = await eventHubsProducerClient.createBatch(batchOptions); + } + + // send any remaining messages, if any. + if (batch.count > 0) { + console.log(`Sending remaining ${batch.count} messages as a single batch.`); + await eventHubsProducerClient.sendBatch(batch); + numEventsSent += batch.count; + } + + console.log(`Sent ${numEventsSent} events`); + + if (numEventsSent !== eventsToSend.length) { + throw new Error(`Not all messages were sent (${numEventsSent}/${eventsToSend.length})`); + } + + // Wait for a bit before cleaning up the sample + setTimeout(async () => { + await eventHubsProducerClient.close(); + console.log(`Exiting sample`); + }, 3 * 1000); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); + +module.exports = { main }; diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/README.md b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/README.md similarity index 54% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/README.md rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/README.md index db12db1e9280..15d1f63710a3 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/README.md +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/README.md @@ -1,10 +1,13 @@ -# Azure Schema Registry client library samples for TypeScript +# Azure Schema Registry client library samples for TypeScript (Beta) These sample programs show how to use the TypeScript client libraries for Azure Schema Registry in some common scenarios. -| **File Name** | **Description** | -| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -| [schemaRegistryAvroSample.ts][schemaregistryavrosample] | Demonstrates the use of SchemaRegistryAvroSerializer to serialize and deserialize using schema from Schema Registry. | +| **File Name** | **Description** | +| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [schemaRegistryAvroSample.ts][schemaregistryavrosample] | Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry. | +| [withEventHubsBufferedProducerClient.ts][witheventhubsbufferedproducerclient] | Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Buffered Producer Client. | +| [withEventHubsConsumerClient.ts][witheventhubsconsumerclient] | Demonstrates the use of AvroSerializer to deserialize messages with avro-serialized payload received from the Event Hub Consumer Client. | +| [withEventHubsProducerClient.ts][witheventhubsproducerclient] | Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Producer Client. | ## Prerequisites @@ -58,7 +61,10 @@ npx cross-env SCHEMA_REGISTRY_ENDPOINT="" SCHEMA_REGIS Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients. -[schemaregistryavrosample]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/src/schemaRegistryAvroSample.ts +[schemaregistryavrosample]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/schemaRegistryAvroSample.ts +[witheventhubsbufferedproducerclient]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsBufferedProducerClient.ts +[witheventhubsconsumerclient]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsConsumerClient.ts +[witheventhubsproducerclient]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsProducerClient.ts [apiref]: https://docs.microsoft.com/javascript/api/@azure/schema-registry-avro [freesub]: https://azure.microsoft.com/free/ [createinstance_azureschemaregistryresource]: https://aka.ms/schemaregistry diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/package.json b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/package.json similarity index 82% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/package.json rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/package.json index 60f93861dc2f..e058ca0d86a9 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/package.json +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/package.json @@ -1,8 +1,8 @@ { - "name": "azure-schema-registry-avro-samples-ts", + "name": "azure-schema-registry-avro-samples-ts-beta", "private": true, "version": "1.0.0", - "description": "Azure Schema Registry client library samples for TypeScript", + "description": "Azure Schema Registry client library samples for TypeScript (Beta)", "engines": { "node": ">=12.0.0" }, @@ -30,9 +30,11 @@ "@azure/schema-registry-avro": "next", "dotenv": "latest", "@azure/identity": "^2.0.1", - "@azure/schema-registry": "1.0.1" + "@azure/schema-registry": "1.0.2", + "@azure/event-hubs": "^5.8.0-beta.1" }, "devDependencies": { + "@types/node": "^12.0.0", "typescript": "~4.4.0", "rimraf": "latest" } diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/sample.env b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/sample.env similarity index 55% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/sample.env rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/sample.env index 18e56c11ef2f..15f5a8fc6249 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/sample.env +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/sample.env @@ -9,3 +9,12 @@ SCHEMA_REGISTRY_GROUP= AZURE_TENANT_ID= AZURE_CLIENT_ID= AZURE_CLIENT_SECRET= + +# Used in samples that use Event Hubs. Retrieve these values from an Event Hub in the Azure portal. +EVENTHUB_CONNECTION_STRING= +EVENTHUB_NAME= +CONSUMER_GROUP_NAME= + +# Used in samples that use Event Grid. Retrieve these values from an Event Grid topic in the Azure portal +EVENT_GRID_TOPIC_ENDPOINT= +EVENT_GRID_TOPIC_API_KEY= \ No newline at end of file diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/src/schemaRegistryAvroSample.ts b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/schemaRegistryAvroSample.ts similarity index 51% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/src/schemaRegistryAvroSample.ts rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/schemaRegistryAvroSample.ts index 0e43f5ee051a..3ff7b9927ee5 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/src/schemaRegistryAvroSample.ts +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/schemaRegistryAvroSample.ts @@ -2,19 +2,22 @@ // Licensed under the MIT License. /** - * @summary Demonstrates the use of SchemaRegistryAvroSerializer to serialize and deserialize using schema from Schema Registry. + * @summary Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry. */ import { DefaultAzureCredential } from "@azure/identity"; import { SchemaRegistryClient, SchemaDescription } from "@azure/schema-registry"; -import { SchemaRegistryAvroSerializer } from "@azure/schema-registry-avro"; +import { AvroSerializer } from "@azure/schema-registry-avro"; // Load the .env file if it exists import * as dotenv from "dotenv"; dotenv.config(); -// Set these environment variables or edit the following values -const endpoint = process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; // Sample Avro Schema for user with first and last names @@ -25,13 +28,13 @@ const schemaObject = { fields: [ { name: "firstName", - type: "string" + type: "string", }, { name: "lastName", - type: "string" - } - ] + type: "string", + }, + ], }; // Matching TypeScript interface for schema @@ -47,31 +50,34 @@ const schemaDescription: SchemaDescription = { name: `${schemaObject.namespace}.${schemaObject.name}`, groupName, format: "Avro", - definition: schema + definition: schema, }; export async function main() { // Create a new client - const client = new SchemaRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); // Register the schema. This would generally have been done somewhere else. - // You can also skip this step and let serialize automatically register schemas - // using autoRegisterSchemas=true, but that is NOT recommended in production. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. await client.registerSchema(schemaDescription); // Create a new serializer backed by the client - const serializer = new SchemaRegistryAvroSerializer(client, { groupName }); + const serializer = new AvroSerializer(client, { groupName }); - // serialize an object that matches the schema + // serialize an object that matches the schema and put it in a message const value: User = { firstName: "Jane", lastName: "Doe" }; - const buffer = await serializer.serialize(value, schema); - console.log("Serialized:"); - console.log(buffer); + const message = await serializer.serializeMessageData(value, schema); + console.log("Created message:"); + console.log(JSON.stringify(message)); - // deserialize the result back to an object - const deserializedValue = (await serializer.deserialize(buffer)) as User; - console.log("Deserialized:"); - console.log(`${deserializedValue.firstName} ${deserializedValue.lastName}`); + // deserialize the message back to an object + const deserializedObject = await serializer.deserializeMessageData(message); + console.log("Deserialized object:"); + console.log(JSON.stringify(deserializedObject as User)); } main().catch((err) => { diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsBufferedProducerClient.ts b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsBufferedProducerClient.ts new file mode 100644 index 000000000000..e576dc4ab16f --- /dev/null +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsBufferedProducerClient.ts @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @summary Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Buffered Producer Client. + */ + +import { DefaultAzureCredential } from "@azure/identity"; +import { SchemaRegistryClient, SchemaDescription } from "@azure/schema-registry"; +import { AvroSerializer } from "@azure/schema-registry-avro"; +import { EventHubBufferedProducerClient, createEventDataAdapter } from "@azure/event-hubs"; + +// Load the .env file if it exists +import * as dotenv from "dotenv"; +dotenv.config(); + +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup +const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; + +// The connection string for Event Hubs +const eventHubsConnectionString = process.env["EVENTHUB_CONNECTION_STRING"] || ""; + +// Sample Avro Schema for user with first and last names +const schemaObject = { + type: "record", + name: "User", + namespace: "com.azure.schemaregistry.samples", + fields: [ + { + name: "firstName", + type: "string", + }, + { + name: "lastName", + type: "string", + }, + ], +}; + +// Matching TypeScript interface for schema +interface User { + firstName: string; + lastName: string; +} + +const schema = JSON.stringify(schemaObject); + +// Description of the schema for registration +const schemaDescription: SchemaDescription = { + name: `${schemaObject.namespace}.${schemaObject.name}`, + groupName, + format: "Avro", + definition: schema, +}; + +async function handleError(): Promise { + console.log("An error occured when sending a message"); +} + +export async function main() { + // Create a new client + const schemaRegistryClient = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); + + // Register the schema. This would generally have been done somewhere else. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. + await schemaRegistryClient.registerSchema(schemaDescription); + + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { + groupName, + messageAdapter: createEventDataAdapter(), + }); + + const eventHubsBufferedProducerClient = new EventHubBufferedProducerClient( + eventHubsConnectionString, + { + onSendEventsErrorHandler: handleError, + } + ); + + // serialize an object that matches the schema + const value: User = { firstName: "Jane", lastName: "Doe" }; + const message = await serializer.serializeMessageData(value, schema); + console.log("Created message:"); + console.log(message); + + await eventHubsBufferedProducerClient.enqueueEvent(message); + console.log(`Message was added to the queue and is about to be sent`); + + // Wait for a bit before cleaning up the sample + setTimeout(async () => { + await eventHubsBufferedProducerClient.close({ flush: true }); + console.log(`Exiting sample`); + }, 30 * 1000); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsConsumerClient.ts b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsConsumerClient.ts new file mode 100644 index 000000000000..d8fe8d63c3a9 --- /dev/null +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsConsumerClient.ts @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @summary Demonstrates the use of AvroSerializer to deserialize messages with avro-serialized payload received from the Event Hub Consumer Client. + */ + +import { DefaultAzureCredential } from "@azure/identity"; +import { SchemaRegistryClient, SchemaDescription } from "@azure/schema-registry"; +import { AvroSerializer } from "@azure/schema-registry-avro"; +import { + EventHubConsumerClient, + earliestEventPosition, + createEventDataAdapter, +} from "@azure/event-hubs"; + +// Load the .env file if it exists +import * as dotenv from "dotenv"; +dotenv.config(); + +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup +const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; + +// The connection string for Event Hubs +const eventHubsConnectionString = process.env["EVENTHUB_CONNECTION_STRING"] || ""; + +// The name of Event Hub the client will connect to +const eventHubName = process.env["EVENTHUB_NAME"] || ""; + +// The name of the Event Hub consumer group from which you want to process events +const consumerGroup = process.env["CONSUMER_GROUP_NAME"] || ""; + +// Sample Avro Schema for user with first and last names +const schemaObject = { + type: "record", + name: "User", + namespace: "com.azure.schemaregistry.samples", + fields: [ + { + name: "firstName", + type: "string", + }, + { + name: "lastName", + type: "string", + }, + ], +}; + +const schema = JSON.stringify(schemaObject); + +// Description of the schema for registration +const schemaDescription: SchemaDescription = { + name: `${schemaObject.namespace}.${schemaObject.name}`, + groupName, + format: "Avro", + definition: schema, +}; + +export async function main() { + // Create a new client + const schemaRegistryClient = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); + + // Register the schema. This would generally have been done somewhere else. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. + await schemaRegistryClient.registerSchema(schemaDescription); + + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { + groupName, + messageAdapter: createEventDataAdapter(), + }); + + const eventHubConsumerClient = new EventHubConsumerClient( + consumerGroup, + eventHubsConnectionString, + eventHubName + ); + + const subscription = eventHubConsumerClient.subscribe( + { + // The callback where you add your code to process incoming events + processEvents: async (events, context) => { + // Note: It is possible for `events` to be an empty array. + // This can happen if there were no new events to receive + // in the `maxWaitTimeInSeconds`, which is defaulted to + // 60 seconds. + // The `maxWaitTimeInSeconds` can be changed by setting + // it in the `options` passed to `subscribe()`. + for (const event of events) { + console.log( + `Received event: '${JSON.stringify(event)}' from partition: '${ + context.partitionId + }' and consumer group: '${context.consumerGroup}'` + ); + if (event.contentType !== undefined && event.body) { + const contentTypeParts = event.contentType.split("+"); + if (contentTypeParts[0] === "avro/binary") { + const deserializedEvent = await serializer.deserializeMessageData(event); + console.log(`Deserialized message: '${JSON.stringify(deserializedEvent)}'`); + } + } + } + }, + processError: async (err, context) => { + console.log(`Error on partition "${context.partitionId}": ${err}`); + }, + }, + { startPosition: earliestEventPosition } + ); + + // Wait for a bit before cleaning up the sample + setTimeout(async () => { + await subscription.close(); + await eventHubConsumerClient.close(); + console.log(`Exiting sample`); + }, 30 * 1000); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsProducerClient.ts b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsProducerClient.ts new file mode 100644 index 000000000000..6a8bb30ba1c1 --- /dev/null +++ b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/src/withEventHubsProducerClient.ts @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @summary Demonstrates the use of AvroSerializer to create messages with avro-serialized payload using schema from Schema Registry and send them to an Event Hub using the EventHub Producer Client. + */ + +import { DefaultAzureCredential } from "@azure/identity"; +import { SchemaRegistryClient, SchemaDescription } from "@azure/schema-registry"; +import { AvroSerializer } from "@azure/schema-registry-avro"; +import { EventHubProducerClient, createEventDataAdapter } from "@azure/event-hubs"; + +// Load the .env file if it exists +import * as dotenv from "dotenv"; +dotenv.config(); + +// The fully qualified namespace for schema registry +const schemaRegistryFullyQualifiedNamespace = + process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; + +// The schema group to use for schema registeration or lookup +const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; + +// The connection string for Event Hubs +const eventHubsConnectionString = process.env["EVENTHUB_CONNECTION_STRING"] || ""; + +// The name of Event Hub the client will connect to +const eventHubName = process.env["EVENTHUB_NAME"] || ""; + +// Sample Avro Schema for user with first and last names +const schemaObject = { + type: "record", + name: "User", + namespace: "com.azure.schemaregistry.samples", + fields: [ + { + name: "firstName", + type: "string", + }, + { + name: "lastName", + type: "string", + }, + ], +}; + +// Matching TypeScript interface for schema +interface User { + firstName: string; + lastName: string; +} + +const schema = JSON.stringify(schemaObject); + +// Description of the schema for registration +const schemaDescription: SchemaDescription = { + name: `${schemaObject.namespace}.${schemaObject.name}`, + groupName, + format: "Avro", + definition: schema, +}; + +export async function main() { + // Create a new client + const schemaRegistryClient = new SchemaRegistryClient( + schemaRegistryFullyQualifiedNamespace, + new DefaultAzureCredential() + ); + + // Register the schema. This would generally have been done somewhere else. + // You can also skip this step and let `serializeMessageData` automatically register + // schemas using autoRegisterSchemas=true, but that is NOT recommended in production. + await schemaRegistryClient.registerSchema(schemaDescription); + + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { + groupName, + messageAdapter: createEventDataAdapter(), + }); + + const eventHubsProducerClient = new EventHubProducerClient( + eventHubsConnectionString, + eventHubName + ); + + // serialize an object that matches the schema + const value: User = { firstName: "Joe", lastName: "Doe" }; + const message = await serializer.serializeMessageData(value, schema); + console.log("Created message:"); + console.log(message); + + const eventsToSend = [message]; + + // By not specifying a partition ID or a partition key we allow the server to choose + // which partition will accept this message. + // + // This pattern works well if the consumers of your events do not have any particular + // requirements about the ordering of batches against other batches or if you don't care + // which messages are assigned to which partition. + // + // If you would like more control you can pass either a `partitionKey` or a `partitionId` + // into the createBatch() `options` parameter which will allow you full control over the + // destination. + const batchOptions = { + // The maxSizeInBytes lets you manually control the size of the batch. + // if this is not set we will get the maximum batch size from Event Hubs. + // + // For this sample you can change the batch size to see how different parts + // of the sample handle batching. In production we recommend using the default + // and not specifying a maximum size. + // + // maxSizeInBytes: 200 + }; + + let batch = await eventHubsProducerClient.createBatch(batchOptions); + + let numEventsSent = 0; + + // add events to our batch + let i = 0; + + while (i < eventsToSend.length) { + // messages can fail to be added to the batch if they exceed the maximum size configured for + // the EventHub. + const isAdded = batch.tryAdd(eventsToSend[i]); + + if (isAdded) { + console.log(`Added a message with index ${i} to the batch`); + ++i; + continue; + } + + if (batch.count === 0) { + // If we can't add it and the batch is empty that means the message we're trying to send + // is too large, even when it would be the _only_ message in the batch. + // + // At this point you'll need to decide if you're okay with skipping this message entirely + // or find some way to shrink it. + console.log(`Message was too large and can't be sent until it's made smaller. Skipping...`); + ++i; + continue; + } + + // otherwise this just signals a good spot to send our batch + console.log(`Batch is full - sending ${batch.count} messages as a single batch.`); + await eventHubsProducerClient.sendBatch(batch); + numEventsSent += batch.count; + + // and create a new one to house the next set of messages + batch = await eventHubsProducerClient.createBatch(batchOptions); + } + + // send any remaining messages, if any. + if (batch.count > 0) { + console.log(`Sending remaining ${batch.count} messages as a single batch.`); + await eventHubsProducerClient.sendBatch(batch); + numEventsSent += batch.count; + } + + console.log(`Sent ${numEventsSent} events`); + + if (numEventsSent !== eventsToSend.length) { + throw new Error(`Not all messages were sent (${numEventsSent}/${eventsToSend.length})`); + } + + // Wait for a bit before cleaning up the sample + setTimeout(async () => { + await eventHubsProducerClient.close(); + console.log(`Exiting sample`); + }, 3 * 1000); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/tsconfig.json b/sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/tsconfig.json similarity index 100% rename from sdk/schemaregistry/schema-registry-avro/samples/v1/typescript/tsconfig.json rename to sdk/schemaregistry/schema-registry-avro/samples/v1-beta/typescript/tsconfig.json diff --git a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/schemaRegistryAvroSample.js b/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/schemaRegistryAvroSample.js deleted file mode 100644 index 39985880df74..000000000000 --- a/sdk/schemaregistry/schema-registry-avro/samples/v1/javascript/schemaRegistryAvroSample.js +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -/** - * @summary Demonstrates the use of SchemaRegistryAvroSerializer to serialize and deserialize using schema from Schema Registry. - */ - -const { DefaultAzureCredential } = require("@azure/identity"); -const { SchemaRegistryClient } = require("@azure/schema-registry"); -const { SchemaRegistryAvroSerializer } = require("@azure/schema-registry-avro"); - -// Load the .env file if it exists -const dotenv = require("dotenv"); -dotenv.config(); - -// Set these environment variables or edit the following values -const endpoint = process.env["SCHEMA_REGISTRY_ENDPOINT"] || ""; -const groupName = process.env["SCHEMA_REGISTRY_GROUP"] || "AzureSdkSampleGroup"; - -// Sample Avro Schema for user with first and last names -const schemaObject = { - type: "record", - name: "User", - namespace: "com.azure.schemaregistry.samples", - fields: [ - { - name: "firstName", - type: "string" - }, - { - name: "lastName", - type: "string" - } - ] -}; - -const schema = JSON.stringify(schemaObject); - -// Description of the schema for registration -const schemaDescription = { - name: `${schemaObject.namespace}.${schemaObject.name}`, - groupName, - format: "Avro", - definition: schema -}; - -async function main() { - // Create a new client - const client = new SchemaRegistryClient(endpoint, new DefaultAzureCredential()); - - // Register the schema. This would generally have been done somewhere else. - // You can also skip this step and let serialize automatically register schemas - // using autoRegisterSchemas=true, but that is NOT recommended in production. - await client.registerSchema(schemaDescription); - - // Create a new serializer backed by the client - const serializer = new SchemaRegistryAvroSerializer(client, { groupName }); - - // serialize an object that matches the schema - const value = { firstName: "Jane", lastName: "Doe" }; - const buffer = await serializer.serialize(value, schema); - console.log("Serialized:"); - console.log(buffer); - - // deserialize the result back to an object - const deserializedValue = await serializer.deserialize(buffer); - console.log("Deserialized:"); - console.log(`${deserializedValue.firstName} ${deserializedValue.lastName}`); -} - -main().catch((err) => { - console.error("The sample encountered an error:", err); -});