@azure/event-hubs
Version:
Azure Event Hubs SDK for JS.
355 lines (354 loc) • 15.1 kB
JavaScript
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