UNPKG

@azure/event-hubs

Version:
355 lines (354 loc) • 15.1 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var eventHubConsumerClient_exports = {}; __export(eventHubConsumerClient_exports, { EventHubConsumerClient: () => EventHubConsumerClient, isCheckpointStore: () => isCheckpointStore }); module.exports = __toCommonJS(eventHubConsumerClient_exports); var import_eventProcessor = require("./eventProcessor.js"); var import_connectionContext = require("./connectionContext.js"); var import_balancedStrategy = require("./loadBalancerStrategies/balancedStrategy.js"); var import_core_amqp = require("@azure/core-amqp"); var import_greedyStrategy = require("./loadBalancerStrategies/greedyStrategy.js"); var import_inMemoryCheckpointStore = require("./inMemoryCheckpointStore.js"); var import_partitionGate = require("./impl/partitionGate.js"); var import_unbalancedStrategy = require("./loadBalancerStrategies/unbalancedStrategy.js"); var import_typeGuards = require("./util/typeGuards.js"); var import_logger = require("./logger.js"); var import_eventPosition = require("./eventPosition.js"); var import_utils = require("./util/utils.js"); const defaultConsumerClientOptions = { // to support our current "process single event only" workflow we'll also purposefully // only request a single event at a time. maxBatchSize: 1, maxWaitTimeInSeconds: 60 }; class EventHubConsumerClient { // #3.1 constructor(_consumerGroup, connectionStringOrFullyQualifiedNamespace2, checkpointStoreOrEventHubNameOrOptions3, checkpointStoreOrCredentialOrOptions4, checkpointStoreOrOptions5, options6) { this._consumerGroup = _consumerGroup; if ((0, import_typeGuards.isCredential)(checkpointStoreOrCredentialOrOptions4)) { import_logger.logger.info("Creating EventHubConsumerClient with TokenCredential."); if (isCheckpointStore(checkpointStoreOrOptions5)) { this._checkpointStore = checkpointStoreOrOptions5; this._userChoseCheckpointStore = true; this._clientOptions = options6 || {}; } else { this._checkpointStore = new import_inMemoryCheckpointStore.InMemoryCheckpointStore(); this._userChoseCheckpointStore = false; this._clientOptions = checkpointStoreOrOptions5 || {}; } this._context = (0, import_connectionContext.createConnectionContext)( connectionStringOrFullyQualifiedNamespace2, checkpointStoreOrEventHubNameOrOptions3, checkpointStoreOrCredentialOrOptions4, this._clientOptions ); } else if (typeof checkpointStoreOrEventHubNameOrOptions3 === "string") { import_logger.logger.info("Creating EventHubConsumerClient with connection string and event hub name."); if (isCheckpointStore(checkpointStoreOrCredentialOrOptions4)) { this._checkpointStore = checkpointStoreOrCredentialOrOptions4; this._userChoseCheckpointStore = true; this._clientOptions = checkpointStoreOrOptions5 || {}; } else { this._checkpointStore = new import_inMemoryCheckpointStore.InMemoryCheckpointStore(); this._userChoseCheckpointStore = false; this._clientOptions = checkpointStoreOrCredentialOrOptions4 || {}; } this._context = (0, import_connectionContext.createConnectionContext)( connectionStringOrFullyQualifiedNamespace2, checkpointStoreOrEventHubNameOrOptions3, this._clientOptions ); } else { import_logger.logger.info("Creating EventHubConsumerClient with connection string."); if (isCheckpointStore(checkpointStoreOrEventHubNameOrOptions3)) { this._checkpointStore = checkpointStoreOrEventHubNameOrOptions3; this._userChoseCheckpointStore = true; this._clientOptions = checkpointStoreOrCredentialOrOptions4 || {}; } else { this._checkpointStore = new import_inMemoryCheckpointStore.InMemoryCheckpointStore(); this._userChoseCheckpointStore = false; this._clientOptions = checkpointStoreOrEventHubNameOrOptions3 || {}; } this._context = (0, import_connectionContext.createConnectionContext)( connectionStringOrFullyQualifiedNamespace2, this._clientOptions ); } this.identifier = this._clientOptions.identifier ?? (0, import_utils.getRandomName)(); this._loadBalancingOptions = { // default options strategy: "balanced", updateIntervalInMs: 1e4, partitionOwnershipExpirationIntervalInMs: 6e4, // options supplied by user ...this._clientOptions?.loadBalancingOptions }; } _consumerGroup; /** * Describes the amqp connection context for the client. */ _context; /** * The options passed by the user when creating the EventHubClient instance. */ _clientOptions; _partitionGate = new import_partitionGate.PartitionGate(); /** * The Subscriptions that were spawned by calling `subscribe()`. * Subscriptions that have been stopped by the user will not * be present in this set. */ _subscriptions = /* @__PURE__ */ new Set(); /** * The name of the default consumer group in the Event Hubs service. */ static defaultConsumerGroupName = import_core_amqp.Constants.defaultConsumerGroup; _checkpointStore; _userChoseCheckpointStore; /** * Options for configuring load balancing. */ _loadBalancingOptions; /** * @readonly * The name of the Event Hub instance for which this client is created. */ get eventHubName() { return this._context.config.entityPath; } /** * @readonly * The fully qualified namespace of the Event Hub instance for which this client is created. * This is likely to be similar to <yournamespace>.servicebus.windows.net. */ get fullyQualifiedNamespace() { return this._context.config.host; } /** * The name used to identify this EventHubConsumerClient. * If not specified or empty, a random unique one will be generated. */ identifier; /** * Closes the AMQP connection to the Event Hub instance, * returning a promise that will be resolved when disconnection is completed. * @returns Promise<void> * @throws Error if the underlying connection encounters an error while closing. */ async close() { const activeSubscriptions = Array.from(this._subscriptions); await Promise.all( activeSubscriptions.map((subscription) => { return subscription.close(); }) ); return this._context.close(); } /** * Provides the id for each partition associated with the Event Hub. * @param options - The set of options to apply to the operation call. * @returns A promise that resolves with an Array of strings representing the id for * each partition associated with the Event Hub. * @throws Error if the underlying connection has been closed, create a new EventHubConsumerClient. * @throws AbortError if the operation is cancelled via the abortSignal. */ async getPartitionIds(options = {}) { const eventHubProperties = await this._context.managementSession.getEventHubProperties({ ...options, retryOptions: this._clientOptions.retryOptions }); return eventHubProperties.partitionIds; } /** * Provides information about the state of the specified partition. * @param partitionId - The id of the partition for which information is required. * @param options - The set of options to apply to the operation call. * @returns A promise that resolves with information about the state of the partition . * @throws Error if the underlying connection has been closed, create a new EventHubConsumerClient. * @throws AbortError if the operation is cancelled via the abortSignal. */ getPartitionProperties(partitionId, options = {}) { return this._context.managementSession.getPartitionProperties(partitionId, { ...options, retryOptions: this._clientOptions.retryOptions }); } /** * Provides the Event Hub runtime information. * @param options - The set of options to apply to the operation call. * @returns A promise that resolves with information about the Event Hub instance. * @throws Error if the underlying connection has been closed, create a new EventHubConsumerClient. * @throws AbortError if the operation is cancelled via the abortSignal. */ getEventHubProperties(options = {}) { return this._context.managementSession.getEventHubProperties({ ...options, retryOptions: this._clientOptions.retryOptions }); } // #2 subscribe(handlersOrPartitionId1, optionsOrHandlers2, possibleOptions3) { let eventProcessor; let targetedPartitionId; if (isSubscriptionEventHandlers(handlersOrPartitionId1)) { const options = optionsOrHandlers2; if (options && options.startPosition) { (0, import_eventPosition.validateEventPositions)(options.startPosition); } ({ targetedPartitionId, eventProcessor } = this.createEventProcessorForAllPartitions( handlersOrPartitionId1, options )); } else if (isSubscriptionEventHandlers(optionsOrHandlers2)) { const options = possibleOptions3; if (options && options.startPosition) { (0, import_eventPosition.validateEventPositions)(options.startPosition); } ({ targetedPartitionId, eventProcessor } = this.createEventProcessorForSinglePartition( // cast to string as downstream code expects partitionId to be string, but JS users could have given us anything. // we don't validate the user input and instead rely on service throwing errors if any String(handlersOrPartitionId1), optionsOrHandlers2, possibleOptions3 )); } else { throw new TypeError("Unhandled subscribe() overload"); } eventProcessor.start(); const subscription = { get isRunning() { return eventProcessor.isRunning(); }, close: () => { this._partitionGate.remove(targetedPartitionId); this._subscriptions.delete(subscription); return eventProcessor.stop(); } }; this._subscriptions.add(subscription); return subscription; } /** * Gets the LoadBalancing strategy that should be used based on what the user provided. */ _getLoadBalancingStrategy() { if (!this._userChoseCheckpointStore) { return new import_unbalancedStrategy.UnbalancedLoadBalancingStrategy(); } const partitionOwnershipExpirationIntervalInMs = this._loadBalancingOptions.partitionOwnershipExpirationIntervalInMs; if (this._loadBalancingOptions?.strategy === "greedy") { return new import_greedyStrategy.GreedyLoadBalancingStrategy(partitionOwnershipExpirationIntervalInMs); } return new import_balancedStrategy.BalancedLoadBalancingStrategy(partitionOwnershipExpirationIntervalInMs); } createEventProcessorForAllPartitions(subscriptionEventHandlers, options) { this._partitionGate.add("all"); if (this._userChoseCheckpointStore) { import_logger.logger.verbose( "EventHubConsumerClient subscribing to all partitions, using a checkpoint store." ); } else { import_logger.logger.verbose("EventHubConsumerClient subscribing to all partitions, no checkpoint store."); } const loadBalancingStrategy = this._getLoadBalancingStrategy(); const eventProcessor = this._createEventProcessor( this._context, subscriptionEventHandlers, this._checkpointStore, { ...defaultConsumerClientOptions, ...options, ownerLevel: getOwnerLevel(options, this._userChoseCheckpointStore), // make it so all the event processors process work with the same overarching owner ID // this allows the EventHubConsumer to unify all the work for any processors that it spawns ownerId: this.identifier, retryOptions: this._clientOptions.retryOptions, loadBalancingStrategy, loopIntervalInMs: this._loadBalancingOptions.updateIntervalInMs } ); return { targetedPartitionId: "all", eventProcessor }; } createEventProcessorForSinglePartition(partitionId, eventHandlers, options) { this._partitionGate.add(partitionId); const subscribeOptions = options; if (this._userChoseCheckpointStore) { import_logger.logger.verbose( `EventHubConsumerClient subscribing to specific partition (${partitionId}), using a checkpoint store.` ); } else { import_logger.logger.verbose( `EventHubConsumerClient subscribing to specific partition (${partitionId}), no checkpoint store.` ); } const eventProcessor = this._createEventProcessor( this._context, eventHandlers, this._checkpointStore, { ...defaultConsumerClientOptions, ...options, processingTarget: partitionId, ownerLevel: getOwnerLevel(subscribeOptions, this._userChoseCheckpointStore), retryOptions: this._clientOptions.retryOptions, loadBalancingStrategy: new import_unbalancedStrategy.UnbalancedLoadBalancingStrategy(), loopIntervalInMs: this._loadBalancingOptions.updateIntervalInMs ?? 1e4 } ); return { targetedPartitionId: partitionId, eventProcessor }; } _createEventProcessor(connectionContext, subscriptionEventHandlers, checkpointStore, options) { return new import_eventProcessor.EventProcessor( this._consumerGroup, connectionContext, subscriptionEventHandlers, checkpointStore, options ); } } function isCheckpointStore(possible) { if (!possible) { return false; } const checkpointStore = possible; return typeof checkpointStore.claimOwnership === "function" && typeof checkpointStore.listCheckpoints === "function" && typeof checkpointStore.listOwnership === "function" && typeof checkpointStore.updateCheckpoint === "function"; } function isSubscriptionEventHandlers(possible) { return typeof possible.processEvents === "function"; } function getOwnerLevel(options, userChoseCheckpointStore) { if (options && options.ownerLevel) { return options.ownerLevel; } if (userChoseCheckpointStore) { return 0; } else { return void 0; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { EventHubConsumerClient, isCheckpointStore }); //# sourceMappingURL=eventHubConsumerClient.js.map