From 993bce47bcfee3b68a2e04e5d76949b6488d4322 Mon Sep 17 00:00:00 2001 From: Deyaaeldeen Almahallawi Date: Tue, 8 Mar 2022 18:41:33 -0500 Subject: [PATCH] [Schema Registry Avro] Rename Encoder to Serializer (#20731) --- .../schema-registry-avro/CHANGELOG.md | 7 + .../schema-registry-avro/README.md | 42 +++--- .../schema-registry-avro/package.json | 2 +- .../review/schema-registry-avro.api.md | 12 +- .../samples-dev/schemaRegistryAvroSample.ts | 22 +-- .../withEventHubsBufferedProducerClient.ts | 14 +- .../withEventHubsConsumerClient.ts | 14 +- .../withEventHubsProducerClient.ts | 14 +- ...gistryAvroEncoder.ts => avroSerializer.ts} | 76 +++++----- .../schema-registry-avro/src/index.ts | 2 +- .../schema-registry-avro/src/models.ts | 14 +- ...Encoder.spec.ts => avroSerializer.spec.ts} | 142 +++++++++--------- .../test/messageAdapter.spec.ts | 12 +- .../{mockedEncoder.ts => mockedSerializer.ts} | 20 +-- 14 files changed, 200 insertions(+), 193 deletions(-) rename sdk/schemaregistry/schema-registry-avro/src/{schemaRegistryAvroEncoder.ts => avroSerializer.ts} (73%) rename sdk/schemaregistry/schema-registry-avro/test/{avroEncoder.spec.ts => avroSerializer.spec.ts} (54%) rename sdk/schemaregistry/schema-registry-avro/test/utils/{mockedEncoder.ts => mockedSerializer.ts} (57%) diff --git a/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md b/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md index a5729ff4afba..4fb81d3099d8 100644 --- a/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md +++ b/sdk/schemaregistry/schema-registry-avro/CHANGELOG.md @@ -1,5 +1,12 @@ # Release History +## 1.0.0-beta.7 (Unreleased) + +### Breaking Changes +- `AvroEncoder` has been renamed to `AvroSerializer` +- The `encodeMessageData` method has been renamed to `serializeMessageData` +- The `decodeMessageData` method has been renamed to `deserializeMessageData` + ## 1.0.0-beta.6 (2022-02-10) ### Features Added diff --git a/sdk/schemaregistry/schema-registry-avro/README.md b/sdk/schemaregistry/schema-registry-avro/README.md index b77377d47068..19a78416456a 100644 --- a/sdk/schemaregistry/schema-registry-avro/README.md +++ b/sdk/schemaregistry/schema-registry-avro/README.md @@ -1,9 +1,9 @@ -# Azure Schema Registry Avro Encoder client library for JavaScript +# Azure Schema Registry Avro Serializer client library for JavaScript Azure Schema Registry is a schema repository service hosted by Azure Event Hubs, providing schema storage, versioning, and management. This package provides an -Avro encoder capable of encoding and decoding payloads containing -Avro-encoded data. +Avro serializer capable of serializing and deserializing payloads containing +Avro-serialized data. Key links: @@ -31,58 +31,58 @@ npm install @azure/schema-registry-avro ## Key concepts -### AvroEncoder +### AvroSerializer -Provides API to encode to and decode from Avro Binary Encoding wrapped in a message +Provides API to serialize to and deserialize from Avro Binary Encoding wrapped in a message with a content type field containing the schema ID. Uses `SchemaRegistryClient` from the [@azure/schema-registry](https://www.npmjs.com/package/@azure/schema-registry) package to get schema IDs from schema definition or vice versa. The provided API has internal cache to avoid calling the schema registry service when possible. ### Messages -By default, the encoder will create messages structured as follows: +By default, the serializer will create messages structured as follows: - `body`: a byte array containing data in the Avro Binary Encoding. Note that it is NOT Avro Object Container File. The latter includes the schema and creating - it defeats the purpose of using this encoder to move the schema out of the + it defeats the purpose of using this serializer to move the schema out of the message payload and into the schema registry. - `contentType`: a string of the following format `avro/binary+` where - the `avro/binary` part signals that this message has an Avro-encoded payload + the `avro/binary` part signals that this message has an Avro-serialized payload and the `` part is the Schema ID the Schema Registry service assigned - to the schema used to encode this payload. + to the schema used to serialize this payload. Not all messaging services are supporting the same message structure. To enable -integration with such services, the encoder can act on custom message structures +integration with such services, the serializer can act on custom message structures by setting the `messageAdapter` option in the constructor with a corresponding message producer and consumer. Azure messaging client libraries export default adapters for their message types. ### Backward Compatibility -The encoder v1.0.0-beta.5 and under encodes data into binary arrays. Starting from -v1.0.0-beta.6, the encoder returns messages instead that contain the encoded payload. -For a smooth transition to using the newer versions, the encoder also supports -decoding messages with payloads that follow the old format where the schema ID +The serializer v1.0.0-beta.5 and under serializes data into binary arrays. Starting from +v1.0.0-beta.6, the serializer returns messages instead that contain the serialized payload. +For a smooth transition to using the newer versions, the serializer also supports +deserializing messages with payloads that follow the old format where the schema ID is part of the payload. This backward compatibility is temporary and will be removed in v1.0.0. ## Examples -### Encode and decode an `@azure/event-hubs`'s `EventData` +### Serialize and deserialize an `@azure/event-hubs`'s `EventData` ```javascript const { DefaultAzureCredential } = require("@azure/identity"); import { createEventDataAdapter } from "@azure/event-hubs"; const { SchemaRegistryClient } = require("@azure/schema-registry"); -const { AvroEncoder } = require("@azure/schema-registry-avro"); +const { AvroSerializer } = require("@azure/schema-registry-avro"); const client = new SchemaRegistryClient( "", new DefaultAzureCredential() ); -const encoder = new AvroEncoder(client, { +const serializer = new AvroSerializer(client, { groupName: "", messageAdapter: createEventDataAdapter(), }); @@ -98,11 +98,11 @@ const schema = JSON.stringify({ // Example value that matches the Avro schema above const value = { score: 42 }; -// Encode value to a message -const message = await encoder.encodeMessageData(value, schema); +// Serialize value to a message +const message = await serializer.serializeMessageData(value, schema); -// Decode a message to value -const decodedValue = await encoder.decodeMessageData(message); +// Deserialize a message to value +const deserializedValue = await serializer.deserializeMessageData(message); ``` ## Troubleshooting diff --git a/sdk/schemaregistry/schema-registry-avro/package.json b/sdk/schemaregistry/schema-registry-avro/package.json index 9b944fb59086..18af5d7256a9 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.6", + "version": "1.0.0-beta.7", "description": "Schema Registry Avro Serializer Library with typescript type definitions for node.js and browser.", "sdk-type": "client", "main": "dist/index.js", diff --git a/sdk/schemaregistry/schema-registry-avro/review/schema-registry-avro.api.md b/sdk/schemaregistry/schema-registry-avro/review/schema-registry-avro.api.md index 0408fe106c8a..f4c5ae0d3e0d 100644 --- a/sdk/schemaregistry/schema-registry-avro/review/schema-registry-avro.api.md +++ b/sdk/schemaregistry/schema-registry-avro/review/schema-registry-avro.api.md @@ -7,21 +7,21 @@ import { SchemaRegistry } from '@azure/schema-registry'; // @public -export class AvroEncoder { - constructor(client: SchemaRegistry, options?: AvroEncoderOptions); - decodeMessageData(message: MessageT, options?: DecodeMessageDataOptions): Promise; - encodeMessageData(value: unknown, schema: string): Promise; +export class AvroSerializer { + constructor(client: SchemaRegistry, options?: AvroSerializerOptions); + deserializeMessageData(message: MessageT, options?: DeserializeMessageDataOptions): Promise; + serializeMessageData(value: unknown, schema: string): Promise; } // @public -export interface AvroEncoderOptions { +export interface AvroSerializerOptions { autoRegisterSchemas?: boolean; groupName?: string; messageAdapter?: MessageAdapter; } // @public -export interface DecodeMessageDataOptions { +export interface DeserializeMessageDataOptions { schema?: string; } diff --git a/sdk/schemaregistry/schema-registry-avro/samples-dev/schemaRegistryAvroSample.ts b/sdk/schemaregistry/schema-registry-avro/samples-dev/schemaRegistryAvroSample.ts index 97a70e8df3dd..3ff7b9927ee5 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples-dev/schemaRegistryAvroSample.ts +++ b/sdk/schemaregistry/schema-registry-avro/samples-dev/schemaRegistryAvroSample.ts @@ -2,12 +2,12 @@ // Licensed under the MIT License. /** - * @summary Demonstrates the use of SchemaRegistryAvroEncoder to create messages with avro-encoded payload 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 { AvroEncoder } from "@azure/schema-registry-avro"; +import { AvroSerializer } from "@azure/schema-registry-avro"; // Load the .env file if it exists import * as dotenv from "dotenv"; @@ -61,23 +61,23 @@ export async function main() { ); // Register the schema. This would generally have been done somewhere else. - // You can also skip this step and let `encodeMessageData` automatically register + // 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 encoder backed by the client - const encoder = new AvroEncoder(client, { groupName }); + // Create a new serializer backed by the client + const serializer = new AvroSerializer(client, { groupName }); - // encode an object that matches the schema and put it in a message + // serialize an object that matches the schema and put it in a message const value: User = { firstName: "Jane", lastName: "Doe" }; - const message = await encoder.encodeMessageData(value, schema); + const message = await serializer.serializeMessageData(value, schema); console.log("Created message:"); console.log(JSON.stringify(message)); - // decode the message back to an object - const decodedObject = await encoder.decodeMessageData(message); - console.log("Decoded object:"); - console.log(JSON.stringify(decodedObject as User)); + // 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-dev/withEventHubsBufferedProducerClient.ts b/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsBufferedProducerClient.ts index 7d510201822c..e576dc4ab16f 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsBufferedProducerClient.ts +++ b/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsBufferedProducerClient.ts @@ -2,12 +2,12 @@ // Licensed under the MIT License. /** - * @summary Demonstrates the use of SchemaRegistryAvroEncoder to create messages with avro-encoded payload using schema from Schema Registry and send them to an Event Hub using the EventHub Buffered Producer Client. + * @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 { AvroEncoder } from "@azure/schema-registry-avro"; +import { AvroSerializer } from "@azure/schema-registry-avro"; import { EventHubBufferedProducerClient, createEventDataAdapter } from "@azure/event-hubs"; // Load the .env file if it exists @@ -69,12 +69,12 @@ export async function main() { ); // Register the schema. This would generally have been done somewhere else. - // You can also skip this step and let `encodeMessageData` automatically register + // 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 encoder backed by the client - const encoder = new AvroEncoder(schemaRegistryClient, { + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { groupName, messageAdapter: createEventDataAdapter(), }); @@ -86,9 +86,9 @@ export async function main() { } ); - // encode an object that matches the schema + // serialize an object that matches the schema const value: User = { firstName: "Jane", lastName: "Doe" }; - const message = await encoder.encodeMessageData(value, schema); + const message = await serializer.serializeMessageData(value, schema); console.log("Created message:"); console.log(message); diff --git a/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsConsumerClient.ts b/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsConsumerClient.ts index 1a675158d7d8..d8fe8d63c3a9 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsConsumerClient.ts +++ b/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsConsumerClient.ts @@ -2,12 +2,12 @@ // Licensed under the MIT License. /** - * @summary Demonstrates the use of SchemaRegistryAvroEncoder to decode messages with avro-encoded payload received from the Event Hub Consumer Client. + * @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 { AvroEncoder } from "@azure/schema-registry-avro"; +import { AvroSerializer } from "@azure/schema-registry-avro"; import { EventHubConsumerClient, earliestEventPosition, @@ -69,12 +69,12 @@ export async function main() { ); // Register the schema. This would generally have been done somewhere else. - // You can also skip this step and let `encodeMessageData` automatically register + // 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 encoder backed by the client - const encoder = new AvroEncoder(schemaRegistryClient, { + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { groupName, messageAdapter: createEventDataAdapter(), }); @@ -104,8 +104,8 @@ export async function main() { if (event.contentType !== undefined && event.body) { const contentTypeParts = event.contentType.split("+"); if (contentTypeParts[0] === "avro/binary") { - const decodedEvent = await encoder.decodeMessageData(event); - console.log(`Decoded message: '${JSON.stringify(decodedEvent)}'`); + const deserializedEvent = await serializer.deserializeMessageData(event); + console.log(`Deserialized message: '${JSON.stringify(deserializedEvent)}'`); } } } diff --git a/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsProducerClient.ts b/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsProducerClient.ts index 91837e53b1fe..6a8bb30ba1c1 100644 --- a/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsProducerClient.ts +++ b/sdk/schemaregistry/schema-registry-avro/samples-dev/withEventHubsProducerClient.ts @@ -2,12 +2,12 @@ // Licensed under the MIT License. /** - * @summary Demonstrates the use of SchemaRegistryAvroEncoder to create messages with avro-encoded payload using schema from Schema Registry and send them to an Event Hub using the EventHub Producer Client. + * @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 { AvroEncoder } from "@azure/schema-registry-avro"; +import { AvroSerializer } from "@azure/schema-registry-avro"; import { EventHubProducerClient, createEventDataAdapter } from "@azure/event-hubs"; // Load the .env file if it exists @@ -68,12 +68,12 @@ export async function main() { ); // Register the schema. This would generally have been done somewhere else. - // You can also skip this step and let `encodeMessageData` automatically register + // 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 encoder backed by the client - const encoder = new AvroEncoder(schemaRegistryClient, { + // Create a new serializer backed by the client + const serializer = new AvroSerializer(schemaRegistryClient, { groupName, messageAdapter: createEventDataAdapter(), }); @@ -83,9 +83,9 @@ export async function main() { eventHubName ); - // encode an object that matches the schema + // serialize an object that matches the schema const value: User = { firstName: "Joe", lastName: "Doe" }; - const message = await encoder.encodeMessageData(value, schema); + const message = await serializer.serializeMessageData(value, schema); console.log("Created message:"); console.log(message); diff --git a/sdk/schemaregistry/schema-registry-avro/src/schemaRegistryAvroEncoder.ts b/sdk/schemaregistry/schema-registry-avro/src/avroSerializer.ts similarity index 73% rename from sdk/schemaregistry/schema-registry-avro/src/schemaRegistryAvroEncoder.ts rename to sdk/schemaregistry/schema-registry-avro/src/avroSerializer.ts index e388869c6469..0856fb2be924 100644 --- a/sdk/schemaregistry/schema-registry-avro/src/schemaRegistryAvroEncoder.ts +++ b/sdk/schemaregistry/schema-registry-avro/src/avroSerializer.ts @@ -3,8 +3,8 @@ import * as avro from "avsc"; import { - AvroEncoderOptions, - DecodeMessageDataOptions, + AvroSerializerOptions, + DeserializeMessageDataOptions, MessageAdapter, MessageWithMetadata, } from "./models"; @@ -13,14 +13,14 @@ import LRUCache from "lru-cache"; import LRUCacheOptions = LRUCache.Options; import { isMessageWithMetadata } from "./utility"; -type AVSCEncoder = avro.Type; +type AVSCSerializer = avro.Type; interface CacheEntry { /** Schema ID */ id: string; /** avsc-specific representation for schema */ - encoder: AVSCEncoder; + serializer: AVSCSerializer; } const avroMimeType = "avro/binary"; @@ -29,17 +29,17 @@ const cacheOptions: LRUCacheOptions = { }; /** - * Avro encoder that obtains schemas from a schema registry and does not + * Avro serializer that obtains schemas from a schema registry and does not * pack schemas into its payloads. */ -export class AvroEncoder { +export class AvroSerializer { /** - * Creates a new encoder. + * Creates a new serializer. * * @param client - Schema Registry where schemas are registered and obtained. * Usually this is a SchemaRegistryClient instance. */ - constructor(client: SchemaRegistry, options?: AvroEncoderOptions) { + constructor(client: SchemaRegistry, options?: AvroSerializerOptions) { this.registry = client; this.schemaGroup = options?.groupName; this.autoRegisterSchemas = options?.autoRegisterSchemas ?? false; @@ -51,20 +51,20 @@ export class AvroEncoder { private readonly autoRegisterSchemas: boolean; private readonly messageAdapter?: MessageAdapter; private readonly cacheBySchemaDefinition = new LRUCache(cacheOptions); - private readonly cacheById = new LRUCache(cacheOptions); + private readonly cacheById = new LRUCache(cacheOptions); /** - * encodes the value parameter according to the input schema and creates a message - * with the encoded data. + * serializes the value parameter according to the input schema and creates a message + * with the serialized data. * - * @param value - The value to encodeMessageData. + * @param value - The value to serializeMessageData. * @param schema - The Avro schema to use. - * @returns A new message with the encoded value. The structure of message is + * @returns A new message with the serialized value. The structure of message is * constrolled by the message factory option. */ - async encodeMessageData(value: unknown, schema: string): Promise { + async serializeMessageData(value: unknown, schema: string): Promise { const entry = await this.getSchemaByDefinition(schema); - const buffer = entry.encoder.toBuffer(value); + const buffer = entry.serializer.toBuffer(value); const payload = new Uint8Array( buffer.buffer, buffer.byteOffset, @@ -88,32 +88,32 @@ export class AvroEncoder { } /** - * Decodes the payload of the message using the schema ID in the content type + * Deserializes the payload of the message using the schema ID in the content type * field if no schema was provided. * - * @param message - The message with the payload to be decoded. + * @param message - The message with the payload to be deserialized. * @param options - Decoding options. - * @returns The decoded value. + * @returns The deserialized value. */ - async decodeMessageData( + async deserializeMessageData( message: MessageT, - options: DecodeMessageDataOptions = {} + options: DeserializeMessageDataOptions = {} ): Promise { const { schema: readerSchema } = options; const { body, contentType } = convertMessage(message, this.messageAdapter); const buffer = Buffer.from(body); const writerSchemaId = getSchemaId(contentType); - const writerSchemaEncoder = await this.getSchemaById(writerSchemaId); + const writerSchemaSerializer = await this.getSchemaById(writerSchemaId); if (readerSchema) { - const readerSchemaEncoder = getEncoderForSchema(readerSchema); - const resolver = readerSchemaEncoder.createResolver(writerSchemaEncoder); - return readerSchemaEncoder.fromBuffer(buffer, resolver, true); + const readerSchemaSerializer = getSerializerForSchema(readerSchema); + const resolver = readerSchemaSerializer.createResolver(writerSchemaSerializer); + return readerSchemaSerializer.fromBuffer(buffer, resolver, true); } else { - return writerSchemaEncoder.fromBuffer(buffer); + return writerSchemaSerializer.fromBuffer(buffer); } } - private async getSchemaById(schemaId: string): Promise { + private async getSchemaById(schemaId: string): Promise { const cached = this.cacheById.get(schemaId); if (cached) { return cached; @@ -130,8 +130,8 @@ export class AvroEncoder { ); } - const avroType = getEncoderForSchema(schemaResponse.definition); - return this.cache(schemaId, schemaResponse.definition, avroType).encoder; + const avroType = getSerializerForSchema(schemaResponse.definition); + return this.cache(schemaId, schemaResponse.definition, avroType).serializer; } private async getSchemaByDefinition(schema: string): Promise { @@ -140,14 +140,14 @@ export class AvroEncoder { return cached; } - const avroType = getEncoderForSchema(schema); + const avroType = getSerializerForSchema(schema); if (!avroType.name) { throw new Error("Schema must have a name."); } if (!this.schemaGroup) { throw new Error( - "Schema group must have been specified in the constructor options when the client was created in order to encode." + "Schema group must have been specified in the constructor options when the client was created in order to serialize." ); } @@ -178,10 +178,10 @@ export class AvroEncoder { return this.cache(id, schema, avroType); } - private cache(id: string, schema: string, encoder: AVSCEncoder): CacheEntry { - const entry = { id, encoder }; + private cache(id: string, schema: string, serializer: AVSCSerializer): CacheEntry { + const entry = { id, serializer }; this.cacheBySchemaDefinition.set(schema, entry); - this.cacheById.set(id, encoder); + this.cacheById.set(id, serializer); return entry; } } @@ -193,14 +193,14 @@ function getSchemaId(contentType: string): string { } if (contentTypeParts[0] !== avroMimeType) { throw new Error( - `Received content of type ${contentTypeParts[0]} but an avro encoder may only be used on content that is of '${avroMimeType}' type` + `Received content of type ${contentTypeParts[0]} but an avro serializer may only be used on content that is of '${avroMimeType}' type` ); } return contentTypeParts[1]; } /** - * Tries to decode a body in the preamble format. If that does not succeed, it + * Tries to deserialize a body in the preamble format. If that does not succeed, it * returns it as is. * @param body - The message body * @param contentType - The message content type @@ -229,13 +229,13 @@ function convertMessage( return convertPayload(message.body, message.contentType); } else { throw new Error( - `Expected either a message adapter to be provided to the encoder or the input message to have body and contentType fields` + `Expected either a message adapter to be provided to the serializer or the input message to have body and contentType fields` ); } } /** - * Maintains backward compatability by supporting the encoded value format created + * Maintains backward compatability by supporting the serialized value format created * by earlier beta serializers * @param buffer - The input buffer * @returns a message that contains the body and content type with the schema ID @@ -260,6 +260,6 @@ function tryReadingPreambleFormat(buffer: Buffer): MessageWithMetadata { }; } -function getEncoderForSchema(schema: string): AVSCEncoder { +function getSerializerForSchema(schema: string): AVSCSerializer { return avro.Type.forSchema(JSON.parse(schema), { omitRecordMethods: true }); } diff --git a/sdk/schemaregistry/schema-registry-avro/src/index.ts b/sdk/schemaregistry/schema-registry-avro/src/index.ts index 0d7e2d314fab..f54ff47b8f07 100644 --- a/sdk/schemaregistry/schema-registry-avro/src/index.ts +++ b/sdk/schemaregistry/schema-registry-avro/src/index.ts @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export { AvroEncoder } from "./schemaRegistryAvroEncoder"; +export { AvroSerializer } from "./avroSerializer"; export * from "./models"; diff --git a/sdk/schemaregistry/schema-registry-avro/src/models.ts b/sdk/schemaregistry/schema-registry-avro/src/models.ts index f91d03524786..a949ba69ed82 100644 --- a/sdk/schemaregistry/schema-registry-avro/src/models.ts +++ b/sdk/schemaregistry/schema-registry-avro/src/models.ts @@ -33,9 +33,9 @@ export interface MessageAdapter { /** * Options for Schema */ -export interface AvroEncoderOptions { +export interface AvroSerializerOptions { /** - * When true, register new schemas passed to encodeMessageData. Otherwise, and by + * When true, register new schemas passed to serializeMessageData. Otherwise, and by * default, fail if schema has not already been registered. * * Automatic schema registration is NOT recommended for production scenarios. @@ -43,21 +43,21 @@ export interface AvroEncoderOptions { autoRegisterSchemas?: boolean; /** * The group name to be used when registering/looking up a schema. Must be specified - * if `encodeMessageData` will be called. + * if `serializeMessageData` will be called. */ groupName?: string; /** - * Message Adapter enables the encoder to produce and consume custom messages. + * Message Adapter enables the serializer to produce and consume custom messages. */ messageAdapter?: MessageAdapter; } /** - * The options to the decodeMessageData method. + * The options to the deserializeMessageData method. */ -export interface DecodeMessageDataOptions { +export interface DeserializeMessageDataOptions { /** - * The schema to be used for decoding. + * The schema to be used for deserializing. */ schema?: string; } diff --git a/sdk/schemaregistry/schema-registry-avro/test/avroEncoder.spec.ts b/sdk/schemaregistry/schema-registry-avro/test/avroSerializer.spec.ts similarity index 54% rename from sdk/schemaregistry/schema-registry-avro/test/avroEncoder.spec.ts rename to sdk/schemaregistry/schema-registry-avro/test/avroSerializer.spec.ts index 3cc9842a673d..e17e763d6991 100644 --- a/sdk/schemaregistry/schema-registry-avro/test/avroEncoder.spec.ts +++ b/sdk/schemaregistry/schema-registry-avro/test/avroSerializer.spec.ts @@ -2,10 +2,10 @@ // Licensed under the MIT license. import { - CreateTestEncoderOptions, - createTestEncoder, + CreateTestSerializerOptions, + createTestSerializer, registerTestSchema, -} from "./utils/mockedEncoder"; +} from "./utils/mockedSerializer"; import { assert, use as chaiUse } from "chai"; import { testAvroType, testGroup, testSchema, testSchemaIds, testValue } from "./utils/dummies"; import chaiPromises from "chai-as-promised"; @@ -13,15 +13,15 @@ import { createTestRegistry } from "./utils/mockedRegistryClient"; chaiUse(chaiPromises); -const noAutoRegisterOptions: CreateTestEncoderOptions = { - encoderOptions: { autoRegisterSchemas: false, groupName: testGroup }, +const noAutoRegisterOptions: CreateTestSerializerOptions = { + serializerOptions: { autoRegisterSchemas: false, groupName: testGroup }, }; -describe("AvroEncoder", function () { +describe("AvroSerializer", function () { it("rejects invalid format", async () => { - const encoder = await createTestEncoder(); + const serializer = await createTestSerializer(); await assert.isRejected( - encoder.decodeMessageData({ + serializer.deserializeMessageData({ body: Buffer.alloc(1), contentType: "application/json+1234", }), @@ -30,14 +30,14 @@ describe("AvroEncoder", function () { }); it("rejects schema with no name", async () => { - const encoder = await createTestEncoder(); + const serializer = await createTestSerializer(); const schema = JSON.stringify({ type: "record", fields: [] }); - await assert.isRejected(encoder.encodeMessageData({}, schema), /name/); + await assert.isRejected(serializer.serializeMessageData({}, schema), /name/); }); it("rejects a schema with different format", async () => { const registry = createTestRegistry(true); // true means never live, we can't register non-avro schema in live service - const encoder = await createTestEncoder({ + const serializer = await createTestSerializer({ ...noAutoRegisterOptions, registry, }); @@ -49,7 +49,7 @@ describe("AvroEncoder", function () { }); await assert.isRejected( - encoder.decodeMessageData({ + serializer.deserializeMessageData({ body: Buffer.alloc(1), contentType: `avro/binary+${schema.id}`, }), @@ -57,22 +57,22 @@ describe("AvroEncoder", function () { ); }); - it("rejects encoding when schema is not found", async () => { - const encoder = await createTestEncoder(noAutoRegisterOptions); + it("rejects serializing when schema is not found", async () => { + const serializer = await createTestSerializer(noAutoRegisterOptions); const schema = JSON.stringify({ type: "record", name: "NeverRegistered", namespace: "my.example", fields: [{ name: "count", type: "int" }], }); - await assert.isRejected(encoder.encodeMessageData({ count: 42 }, schema), /not found/); + await assert.isRejected(serializer.serializeMessageData({ count: 42 }, schema), /not found/); }); - it("rejects decoding when schema is not found", async () => { - const encoder = await createTestEncoder(noAutoRegisterOptions); + it("rejects deserializing when schema is not found", async () => { + const serializer = await createTestSerializer(noAutoRegisterOptions); const payload = testAvroType.toBuffer(testValue); await assert.isRejected( - encoder.decodeMessageData({ + serializer.deserializeMessageData({ body: payload, contentType: `avro/binary+${testSchemaIds[1]}`, }), @@ -80,31 +80,31 @@ describe("AvroEncoder", function () { ); }); - it("encodes to the expected format", async () => { + it("serializes to the expected format", async () => { const registry = createTestRegistry(); const schemaId = await registerTestSchema(registry); - const encoder = await createTestEncoder({ ...noAutoRegisterOptions, registry }); - const message = await encoder.encodeMessageData(testValue, testSchema); + const serializer = await createTestSerializer({ ...noAutoRegisterOptions, registry }); + const message = await serializer.serializeMessageData(testValue, testSchema); assert.isUndefined((message.body as Buffer).readBigInt64BE); const buffer = Buffer.from(message.body); assert.strictEqual(`avro/binary+${schemaId}`, message.contentType); assert.deepStrictEqual(testAvroType.fromBuffer(buffer), testValue); - assert.equal(encoder["cacheById"].length, 1); + assert.equal(serializer["cacheById"].length, 1); assert.equal( - encoder["cacheById"].peek(schemaId)?.name, + serializer["cacheById"].peek(schemaId)?.name, "com.azure.schemaregistry.samples.AvroUser" ); - assert.equal(encoder["cacheBySchemaDefinition"].length, 1); - assert.equal(encoder["cacheBySchemaDefinition"].peek(testSchema)?.id, schemaId); + assert.equal(serializer["cacheBySchemaDefinition"].length, 1); + assert.equal(serializer["cacheBySchemaDefinition"].peek(testSchema)?.id, schemaId); }); - it("decodes from the expected format", async () => { + it("deserializes from the expected format", async () => { const registry = createTestRegistry(); const schemaId = await registerTestSchema(registry); - const encoder = await createTestEncoder({ ...noAutoRegisterOptions, registry }); + const serializer = await createTestSerializer({ ...noAutoRegisterOptions, registry }); const payload = testAvroType.toBuffer(testValue); assert.deepStrictEqual( - await encoder.decodeMessageData({ + await serializer.deserializeMessageData({ body: payload, contentType: `avro/binary+${schemaId}`, }), @@ -112,26 +112,26 @@ describe("AvroEncoder", function () { ); }); - it("encodes and decodes in round trip", async () => { - let encoder = await createTestEncoder(); - let message = await encoder.encodeMessageData(testValue, testSchema); - assert.deepStrictEqual(await encoder.decodeMessageData(message), testValue); + it("serializes and deserializes in round trip", async () => { + let serializer = await createTestSerializer(); + let message = await serializer.serializeMessageData(testValue, testSchema); + assert.deepStrictEqual(await serializer.deserializeMessageData(message), testValue); - // again for cache hit coverage on encodeMessageData - message = await encoder.encodeMessageData(testValue, testSchema); - assert.deepStrictEqual(await encoder.decodeMessageData(message), testValue); + // again for cache hit coverage on serializeMessageData + message = await serializer.serializeMessageData(testValue, testSchema); + assert.deepStrictEqual(await serializer.deserializeMessageData(message), testValue); - // throw away encoder for cache miss coverage on decodeMessageData - encoder = await createTestEncoder(noAutoRegisterOptions); - assert.deepStrictEqual(await encoder.decodeMessageData(message), testValue); + // throw away serializer for cache miss coverage on deserializeMessageData + serializer = await createTestSerializer(noAutoRegisterOptions); + assert.deepStrictEqual(await serializer.deserializeMessageData(message), testValue); - // throw away encoder again and cover getSchemaProperties instead of registerSchema - encoder = await createTestEncoder(noAutoRegisterOptions); - assert.deepStrictEqual(await encoder.encodeMessageData(testValue, testSchema), message); + // throw away serializer again and cover getSchemaProperties instead of registerSchema + serializer = await createTestSerializer(noAutoRegisterOptions); + assert.deepStrictEqual(await serializer.serializeMessageData(testValue, testSchema), message); }); it("works with trivial example in README", async () => { - const encoder = await createTestEncoder(); + const serializer = await createTestSerializer(); // Example Avro schema const schema = JSON.stringify({ @@ -144,19 +144,19 @@ describe("AvroEncoder", function () { // Example value that matches the Avro schema above const value = { score: 42 }; - // encode value to a message - const message = await encoder.encodeMessageData(value, schema); + // serialize value to a message + const message = await serializer.serializeMessageData(value, schema); - // Decode message to value - const decodedValue = await encoder.decodeMessageData(message); + // Deserialize message to value + const deserializedValue = await serializer.deserializeMessageData(message); - assert.deepStrictEqual(decodedValue, value); + assert.deepStrictEqual(deserializedValue, value); }); - it("decodes from a compatible reader schema", async () => { - const encoder = await createTestEncoder(); - const message = await encoder.encodeMessageData(testValue, testSchema); - const decodedValue: any = await encoder.decodeMessageData(message, { + it("deserializes from a compatible reader schema", async () => { + const serializer = await createTestSerializer(); + const message = await serializer.serializeMessageData(testValue, testSchema); + const deserializedValue: any = await serializer.deserializeMessageData(message, { /** * This schema is missing the favoriteNumber field that exists in the writer schema * and adds an "age" field with a default value. @@ -178,16 +178,16 @@ describe("AvroEncoder", function () { ], }), }); - assert.isUndefined(decodedValue.favoriteNumber); - assert.equal(decodedValue.name, testValue.name); - assert.equal(decodedValue.age, 30); + assert.isUndefined(deserializedValue.favoriteNumber); + assert.equal(deserializedValue.name, testValue.name); + assert.equal(deserializedValue.age, 30); }); - it("fails to decode from an incompatible reader schema", async () => { - const encoder = await createTestEncoder(); - const message = await encoder.encodeMessageData(testValue, testSchema); + it("fails to deserialize from an incompatible reader schema", async () => { + const serializer = await createTestSerializer(); + const message = await serializer.serializeMessageData(testValue, testSchema); assert.isRejected( - encoder.decodeMessageData(message, { + serializer.deserializeMessageData(message, { schema: JSON.stringify({ type: "record", name: "AvroUser", @@ -208,17 +208,17 @@ describe("AvroEncoder", function () { ); }); - it("decodes from the old format", async () => { + it("deserializes from the old format", async () => { const registry = createTestRegistry(); const schemaId = await registerTestSchema(registry); - const encoder = await createTestEncoder({ ...noAutoRegisterOptions, registry }); + const serializer = await createTestSerializer({ ...noAutoRegisterOptions, registry }); const payload = testAvroType.toBuffer(testValue); const buffer = Buffer.alloc(36 + payload.length); buffer.write(schemaId, 4, 32, "utf-8"); payload.copy(buffer, 36); assert.deepStrictEqual( - await encoder.decodeMessageData({ + await serializer.deserializeMessageData({ body: buffer, contentType: "avro/binary+000", }), @@ -237,22 +237,22 @@ describe("AvroEncoder", function () { } const registry = createTestRegistry(); - const encoder = await createTestEncoder({ registry }); + const serializer = await createTestSerializer({ registry }); /** * The standard tier resource supports registering up to 25 schemas per a schema group. */ const maxSchemaCount = 25; const maxCacheEntriesCount = Math.floor(maxSchemaCount / 2 - 1); - encoder["cacheById"].max = maxCacheEntriesCount; - encoder["cacheBySchemaDefinition"].max = maxCacheEntriesCount; + serializer["cacheById"].max = maxCacheEntriesCount; + serializer["cacheBySchemaDefinition"].max = maxCacheEntriesCount; const itersCount = 2 * maxCacheEntriesCount; assert.isAtLeast(itersCount, maxCacheEntriesCount + 1); let i = 0; for (; i < itersCount; ++i) { const field1 = makeRndStr(10); const field2 = makeRndStr(10); - const valueToBeEncoded = JSON.parse(`{ "${field1}": "Nick", "${field2}": 42 }`); - const schemaToEncodeWith = JSON.stringify({ + const valueToBeSerialized = JSON.parse(`{ "${field1}": "Nick", "${field2}": 42 }`); + const schemaToSerializeWith = JSON.stringify({ type: "record", name: makeRndStr(8), namespace: "com.azure.schemaregistry.samples", @@ -267,13 +267,13 @@ describe("AvroEncoder", function () { }, ], }); - await encoder.encodeMessageData(valueToBeEncoded, schemaToEncodeWith); + await serializer.serializeMessageData(valueToBeSerialized, schemaToSerializeWith); if (i < maxCacheEntriesCount) { - assert.equal(encoder["cacheById"].length, i + 1); - assert.equal(encoder["cacheBySchemaDefinition"].length, i + 1); + assert.equal(serializer["cacheById"].length, i + 1); + assert.equal(serializer["cacheBySchemaDefinition"].length, i + 1); } else { - assert.equal(encoder["cacheById"].length, maxCacheEntriesCount); - assert.equal(encoder["cacheBySchemaDefinition"].length, maxCacheEntriesCount); + assert.equal(serializer["cacheById"].length, maxCacheEntriesCount); + assert.equal(serializer["cacheBySchemaDefinition"].length, maxCacheEntriesCount); } } }); diff --git a/sdk/schemaregistry/schema-registry-avro/test/messageAdapter.spec.ts b/sdk/schemaregistry/schema-registry-avro/test/messageAdapter.spec.ts index 3b347a827ade..9a9eaae1b867 100644 --- a/sdk/schemaregistry/schema-registry-avro/test/messageAdapter.spec.ts +++ b/sdk/schemaregistry/schema-registry-avro/test/messageAdapter.spec.ts @@ -8,7 +8,7 @@ import { MessagingTestClient } from "./clients/models"; import { assert } from "chai"; import { createEventHubsClient } from "./clients/eventHubs"; import { createMockedMessagingClient } from "./clients/mocked"; -import { createTestEncoder } from "./utils/mockedEncoder"; +import { createTestSerializer } from "./utils/mockedSerializer"; import { env } from "./utils/env"; import { matrix } from "@azure/test-utils"; @@ -90,19 +90,19 @@ describe("Message Adapters", function () { ); }); it("round-tripping with the messaging client", async () => { - const encoder = await createTestEncoder({ - encoderOptions: { + const serializer = await createTestSerializer({ + serializerOptions: { autoRegisterSchemas: false, groupName: testGroup, messageAdapter: createEventDataAdapter(), }, }); - const message = encoder.encodeMessageData(testValue, testSchema); + const message = serializer.serializeMessageData(testValue, testSchema); await adapterTestInfo.client.send(message); const receivedMessage = await adapterTestInfo.client.receive(); await adapterTestInfo.client.cleanup(); - const decodedValue = await encoder.decodeMessageData(receivedMessage); - assert.deepStrictEqual(decodedValue, testValue); + const deserializedValue = await serializer.deserializeMessageData(receivedMessage); + assert.deepStrictEqual(deserializedValue, testValue); }); }); }); diff --git a/sdk/schemaregistry/schema-registry-avro/test/utils/mockedEncoder.ts b/sdk/schemaregistry/schema-registry-avro/test/utils/mockedSerializer.ts similarity index 57% rename from sdk/schemaregistry/schema-registry-avro/test/utils/mockedEncoder.ts rename to sdk/schemaregistry/schema-registry-avro/test/utils/mockedSerializer.ts index 21c41ed73b7b..8b4b90c6a534 100644 --- a/sdk/schemaregistry/schema-registry-avro/test/utils/mockedEncoder.ts +++ b/sdk/schemaregistry/schema-registry-avro/test/utils/mockedSerializer.ts @@ -2,27 +2,27 @@ // Licensed under the MIT license. import { testGroup, testSchema, testSchemaObject } from "./dummies"; -import { AvroEncoder } from "../../src/schemaRegistryAvroEncoder"; -import { AvroEncoderOptions } from "../../src/models"; +import { AvroSerializer } from "../../src/avroSerializer"; +import { AvroSerializerOptions } from "../../src/models"; import { SchemaRegistry } from "@azure/schema-registry"; import { createTestRegistry } from "./mockedRegistryClient"; -export interface CreateTestEncoderOptions { - encoderOptions?: AvroEncoderOptions; +export interface CreateTestSerializerOptions { + serializerOptions?: AvroSerializerOptions; registry?: SchemaRegistry; } -export async function createTestEncoder( - options: CreateTestEncoderOptions = {} -): Promise> { +export async function createTestSerializer( + options: CreateTestSerializerOptions = {} +): Promise> { const { - encoderOptions = { autoRegisterSchemas: true, groupName: testGroup }, + serializerOptions = { autoRegisterSchemas: true, groupName: testGroup }, registry = createTestRegistry(), } = options; - if (!encoderOptions.autoRegisterSchemas) { + if (!serializerOptions.autoRegisterSchemas) { await registerTestSchema(registry); } - return new AvroEncoder(registry, encoderOptions); + return new AvroSerializer(registry, serializerOptions); } export async function registerTestSchema(registry: SchemaRegistry): Promise {