Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / google-gax / build / src / apiCallable.js
diff --git a/legacy-libs/google-gax/build/src/apiCallable.js b/legacy-libs/google-gax/build/src/apiCallable.js
new file mode 100644 (file)
index 0000000..4f3b181
--- /dev/null
@@ -0,0 +1,332 @@
+"use strict";
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+/**
+ * Provides function wrappers that implement page streaming and retrying.
+ */
+const grpc_1 = require("grpc");
+const GoogleError_1 = require("./GoogleError");
+class Canceller {
+    /**
+     * Canceller manages callback, API calls, and cancellation
+     * of the API calls.
+     * @param {APICallback=} callback
+     *   The callback to be called asynchronously when the API call
+     *   finishes.
+     * @constructor
+     * @property {APICallback} callback
+     *   The callback function to be called.
+     * @private
+     */
+    constructor(callback) {
+        this.callback = callback;
+        this.completed = false;
+    }
+    /**
+     * Cancels the ongoing promise.
+     */
+    cancel() {
+        if (this.completed) {
+            return;
+        }
+        this.completed = true;
+        if (this.cancelFunc) {
+            this.cancelFunc();
+        }
+        else {
+            const error = new GoogleError_1.GoogleError('cancelled');
+            error.code = grpc_1.status.CANCELLED;
+            this.callback(error);
+        }
+    }
+    /**
+     * Call calls the specified function. Result will be used to fulfill
+     * the promise.
+     *
+     * @param {function(Object, APICallback=)} aFunc
+     *   A function for an API call.
+     * @param {Object} argument
+     *   A request object.
+     */
+    call(aFunc, argument) {
+        if (this.completed) {
+            return;
+        }
+        // tslint:disable-next-line no-any
+        const canceller = aFunc(argument, (...args) => {
+            this.completed = true;
+            setImmediate(this.callback, ...args);
+        });
+        this.cancelFunc = () => canceller.cancel();
+    }
+}
+exports.Canceller = Canceller;
+// tslint:disable-next-line no-any
+class PromiseCanceller extends Canceller {
+    /**
+     * PromiseCanceller is Canceller, but it holds a promise when
+     * the API call finishes.
+     * @param {Function} PromiseCtor - A constructor for a promise that implements
+     * the ES6 specification of promise.
+     * @constructor
+     * @private
+     */
+    // tslint:disable-next-line variable-name
+    constructor(PromiseCtor) {
+        super();
+        this.promise = new PromiseCtor((resolve, reject) => {
+            this.callback = (err, response, next, rawResponse) => {
+                if (err) {
+                    reject(err);
+                }
+                else {
+                    resolve([response, next, rawResponse]);
+                }
+            };
+        });
+        this.promise.cancel = () => {
+            this.cancel();
+        };
+    }
+}
+exports.PromiseCanceller = PromiseCanceller;
+/**
+ * Updates aFunc so that it gets called with the timeout as its final arg.
+ *
+ * This converts a function, aFunc, into another function with updated deadline.
+ *
+ * @private
+ *
+ * @param {APIFunc} aFunc - a function to be updated.
+ * @param {number} timeout - to be added to the original function as it final
+ *   positional arg.
+ * @param {Object} otherArgs - the additional arguments to be passed to aFunc.
+ * @param {Object=} abTests - the A/B testing key/value pairs.
+ * @return {function(Object, APICallback)}
+ *  the function with other arguments and the timeout.
+ */
+function addTimeoutArg(aFunc, timeout, otherArgs, abTests) {
+    // TODO: this assumes the other arguments consist of metadata and options,
+    // which is specific to gRPC calls. Remove the hidden dependency on gRPC.
+    return function timeoutFunc(argument, callback) {
+        const now = new Date();
+        const options = otherArgs.options || {};
+        options.deadline = new Date(now.getTime() + timeout);
+        const metadata = otherArgs.metadataBuilder ?
+            otherArgs.metadataBuilder(abTests, otherArgs.headers || {}) :
+            null;
+        return aFunc(argument, metadata, options, callback);
+    };
+}
+/**
+ * Creates a function equivalent to aFunc, but that retries on certain
+ * exceptions.
+ *
+ * @private
+ *
+ * @param {APIFunc} aFunc - A function.
+ * @param {RetryOptions} retry - Configures the exceptions upon which the
+ *   function eshould retry, and the parameters to the exponential backoff retry
+ *   algorithm.
+ * @param {Object} otherArgs - the additional arguments to be passed to aFunc.
+ * @return {function(Object, APICallback)} A function that will retry.
+ */
+function retryable(aFunc, retry, otherArgs) {
+    const delayMult = retry.backoffSettings.retryDelayMultiplier;
+    const maxDelay = retry.backoffSettings.maxRetryDelayMillis;
+    const timeoutMult = retry.backoffSettings.rpcTimeoutMultiplier;
+    const maxTimeout = retry.backoffSettings.maxRpcTimeoutMillis;
+    let delay = retry.backoffSettings.initialRetryDelayMillis;
+    let timeout = retry.backoffSettings.initialRpcTimeoutMillis;
+    /**
+     * Equivalent to ``aFunc``, but retries upon transient failure.
+     *
+     * Retrying is done through an exponential backoff algorithm configured
+     * by the options in ``retry``.
+     * @param {Object} argument The request object.
+     * @param {APICallback} callback The callback.
+     * @return {function()} cancel function.
+     */
+    return function retryingFunc(argument, callback) {
+        let canceller;
+        let timeoutId;
+        let now = new Date();
+        let deadline;
+        if (retry.backoffSettings.totalTimeoutMillis) {
+            deadline = now.getTime() + retry.backoffSettings.totalTimeoutMillis;
+        }
+        let retries = 0;
+        const maxRetries = retry.backoffSettings.maxRetries;
+        // TODO: define A/B testing values for retry behaviors.
+        /** Repeat the API call as long as necessary. */
+        function repeat() {
+            timeoutId = null;
+            if (deadline && now.getTime() >= deadline) {
+                const error = new GoogleError_1.GoogleError('Retry total timeout exceeded before any response was received');
+                error.code = grpc_1.status.DEADLINE_EXCEEDED;
+                callback(error);
+                return;
+            }
+            if (retries && retries >= maxRetries) {
+                const error = new GoogleError_1.GoogleError('Exceeded maximum number of retries before any ' +
+                    'response was received');
+                error.code = grpc_1.status.DEADLINE_EXCEEDED;
+                callback(error);
+                return;
+            }
+            retries++;
+            const toCall = addTimeoutArg(aFunc, timeout, otherArgs);
+            canceller = toCall(argument, (err, response, next, rawResponse) => {
+                if (!err) {
+                    callback(null, response, next, rawResponse);
+                    return;
+                }
+                canceller = null;
+                if (retry.retryCodes.indexOf(err.code) < 0) {
+                    err.note = 'Exception occurred in retry method that was ' +
+                        'not classified as transient';
+                    callback(err);
+                }
+                else {
+                    const toSleep = Math.random() * delay;
+                    timeoutId = setTimeout(() => {
+                        now = new Date();
+                        delay = Math.min(delay * delayMult, maxDelay);
+                        timeout = Math.min(timeout * timeoutMult, maxTimeout, deadline - now.getTime());
+                        repeat();
+                    }, toSleep);
+                }
+            });
+        }
+        if (maxRetries && deadline) {
+            const error = new GoogleError_1.GoogleError('Cannot set both totalTimeoutMillis and maxRetries ' +
+                'in backoffSettings.');
+            error.code = grpc_1.status.INVALID_ARGUMENT;
+            callback(error);
+        }
+        else {
+            repeat();
+        }
+        return {
+            cancel() {
+                if (timeoutId) {
+                    clearTimeout(timeoutId);
+                }
+                if (canceller) {
+                    canceller.cancel();
+                }
+                else {
+                    const error = new GoogleError_1.GoogleError('cancelled');
+                    error.code = grpc_1.status.CANCELLED;
+                    callback(error);
+                }
+            },
+        };
+    };
+}
+/**
+ * Creates an API caller for normal methods.
+ *
+ * @private
+ * @constructor
+ */
+class NormalApiCaller {
+    init(settings, callback) {
+        if (callback) {
+            return new Canceller(callback);
+        }
+        return new PromiseCanceller(settings.promise);
+    }
+    wrap(func) {
+        return func;
+    }
+    call(apiCall, argument, settings, canceller) {
+        canceller.call(apiCall, argument);
+    }
+    fail(canceller, err) {
+        canceller.callback(err);
+    }
+    result(canceller) {
+        if (canceller.promise) {
+            return canceller.promise;
+        }
+        return;
+    }
+}
+exports.NormalApiCaller = NormalApiCaller;
+/**
+ * Converts an rpc call into an API call governed by the settings.
+ *
+ * In typical usage, `func` will be a promsie to a callable used to make an rpc
+ * request. This will mostly likely be a bound method from a request stub used
+ * to make an rpc call. It is not a direct function but a Promise instance,
+ * because of its asynchronism (typically, obtaining the auth information).
+ *
+ * The result is a function which manages the API call with the given settings
+ * and the options on the invocation.
+ *
+ * @param {Promise.<APIFunc>} funcWithAuth - is a promise to be used to make
+ *   a bare rpc call. This is a Promise instead of a bare function because
+ *   the rpc call will be involeved with asynchronous authentications.
+ * @param {CallSettings} settings - provides the settings for this call
+ * @param {Object=} optDescriptor - optionally specify the descriptor for
+ *   the method call.
+ * @return {APICall} func - a bound method on a request stub used
+ *   to make an rpc call.
+ */
+function createApiCall(funcWithAuth, settings, 
+// tslint:disable-next-line no-any
+optDescriptor) {
+    const apiCaller = optDescriptor ? optDescriptor.apiCaller(settings) : new NormalApiCaller();
+    return function apiCallInner(request, callOptions, callback) {
+        const thisSettings = settings.merge(callOptions);
+        const status = apiCaller.init(thisSettings, callback);
+        funcWithAuth
+            .then(func => {
+            func = apiCaller.wrap(func);
+            const retry = thisSettings.retry;
+            if (retry && retry.retryCodes && retry.retryCodes.length > 0) {
+                return retryable(func, thisSettings.retry, thisSettings.otherArgs);
+            }
+            return addTimeoutArg(func, thisSettings.timeout, thisSettings.otherArgs);
+        })
+            .then(apiCall => {
+            apiCaller.call(apiCall, request, thisSettings, status);
+        })
+            .catch(err => {
+            apiCaller.fail(status, err);
+        });
+        return apiCaller.result(status);
+    };
+}
+exports.createApiCall = createApiCall;
+//# sourceMappingURL=apiCallable.js.map
\ No newline at end of file