@zaplify/gcp-pubsub
Version:
Cloud Pub/Sub Client Library for Node.js
220 lines (219 loc) • 7.12 kB
TypeScript
/*!
* Copyright 2018 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// <reference types="node" />
import { CallOptions, GoogleError, grpc } from 'google-gax';
import defer = require('p-defer');
import { ExponentialRetry } from './exponential-retry';
import { AckResponse, Message, Subscriber } from './subscriber';
import { DebugMessage } from './debug';
/**
* @private
*/
export interface QueuedMessage {
ackId: string;
deadline?: number;
responsePromise?: defer.DeferredPromise<void>;
retryCount: number;
}
/**
* @private
*/
export type QueuedMessages = Array<QueuedMessage>;
export interface BatchOptions {
callOptions?: CallOptions;
maxMessages?: number;
maxMilliseconds?: number;
}
/**
* Error class used to signal a batch failure.
*
* Now that we have exactly-once delivery subscriptions, we'll only
* throw one of these if there was an unknown error.
*
* @class
*
* @param {string} message The error message.
* @param {GoogleError} err The grpc error.
*/
export declare class BatchError extends DebugMessage {
ackIds: string[];
code: grpc.status;
details: string;
constructor(err: GoogleError, ackIds: string[], rpc: string);
}
/**
* @typedef {object} BatchOptions
* @property {object} [callOptions] Request configuration option, outlined
* here: {@link https://googleapis.github.io/gax-nodejs/interfaces/CallOptions.html}.
* @property {number} [maxMessages=3000] Maximum number of messages allowed in
* each batch sent.
* @property {number} [maxMilliseconds=100] Maximum duration to wait before
* sending a batch. Batches can be sent earlier if the maxMessages option
* is met before the configured duration has passed.
*/
/**
* Class for buffering ack/modAck requests.
*
* @private
* @class
*
* @param {Subscriber} sub The subscriber we're queueing requests for.
* @param {BatchOptions} options Batching options.
*/
export declare abstract class MessageQueue {
numPendingRequests: number;
numInFlightRequests: number;
numInRetryRequests: number;
protected _onFlush?: defer.DeferredPromise<void>;
protected _onDrain?: defer.DeferredPromise<void>;
protected _options: BatchOptions;
protected _requests: QueuedMessages;
protected _subscriber: Subscriber;
protected _timer?: NodeJS.Timer;
protected _retrier: ExponentialRetry<QueuedMessage>;
protected _closed: boolean;
protected abstract _sendBatch(batch: QueuedMessages): Promise<QueuedMessages>;
constructor(sub: Subscriber, options?: BatchOptions);
/**
* Shuts down this message queue gracefully. Any acks/modAcks pending in
* the queue or waiting for retry will be removed. If exactly-once delivery
* is enabled on the subscription, we'll send permanent failures to
* anyone waiting on completions; otherwise we'll send successes.
*
* If a flush is desired first, do it before calling close().
*
* @private
*/
close(): void;
/**
* Gets the default buffer time in ms.
*
* @returns {number}
* @private
*/
get maxMilliseconds(): number;
/**
* Adds a message to the queue.
*
* @param {Message} message The message to add.
* @param {number} [deadline] The deadline.
* @private
*/
add({ ackId }: Message, deadline?: number): Promise<void>;
/**
* Retry handler for acks/modacks that have transient failures. Unless
* it's passed the final deadline, we will just re-queue it for sending.
*
* @private
*/
private handleRetry;
/**
* This hook lets a subclass tell the retry handler to go ahead and fail early.
*
* @private
*/
protected shouldFailEarly(message: QueuedMessage): boolean;
/**
* Sends a batch of messages.
* @private
*/
flush(): Promise<void>;
/**
* Returns a promise that resolves after the next flush occurs.
*
* @returns {Promise}
* @private
*/
onFlush(): Promise<void>;
/**
* Returns a promise that resolves when all in-flight messages have settled.
*/
onDrain(): Promise<void>;
/**
* Set the batching options.
*
* @param {BatchOptions} options Batching options.
* @private
*/
setOptions(options: BatchOptions): void;
/**
* Succeed a whole batch of Acks/Modacks for an OK RPC response.
*
* @private
*/
handleAckSuccesses(batch: QueuedMessages): void;
/**
* If we get an RPC failure of any kind, this will take care of deciding
* what to do for each related ack/modAck. Successful ones will have their
* Promises resolved, permanent errors will have their Promises rejected,
* and transients will be returned for retry.
*
* Note that this is only used for subscriptions with exactly-once
* delivery enabled, so _sendBatch() in the classes below take care of
* resolving errors to success; they don't make it here.
*
* @private
*/
handleAckFailures(operation: string, batch: QueuedMessages, rpcError: GoogleError): {
toError: Map<AckResponse, QueuedMessages>;
toRetry: QueuedMessages;
};
/**
* Since we handle our own retries for ack/modAck calls when exactly-once
* delivery is enabled on a subscription, we conditionally need to disable
* the gax retries. This returns an appropriate CallOptions for the
* subclasses to pass down.
*
* @private
*/
protected getCallOptions(): CallOptions | undefined;
}
/**
* Queues up Acknowledge (ack) requests.
*
* @private
* @class
*/
export declare class AckQueue extends MessageQueue {
/**
* Sends a batch of ack requests.
*
* @private
*
* @param {Array.<Array.<string|number>>} batch Array of ackIds and deadlines.
* @return {Promise}
*/
protected _sendBatch(batch: QueuedMessages): Promise<QueuedMessages>;
}
/**
* Queues up ModifyAckDeadline requests and sends them out in batches.
*
* @private
* @class
*/
export declare class ModAckQueue extends MessageQueue {
/**
* Sends a batch of modAck requests. Each deadline requires its own request,
* so we have to group all the ackIds by deadline and send multiple requests.
*
* @private
*
* @param {Array.<Array.<string|number>>} batch Array of ackIds and deadlines.
* @return {Promise}
*/
protected _sendBatch(batch: QueuedMessages): Promise<QueuedMessages>;
protected shouldFailEarly(message: QueuedMessage): boolean;
}