UNPKG

4.69 kBJavaScriptView Raw
1"use strict";
2// Copyright 2016 Google LLC
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15Object.defineProperty(exports, "__esModule", { value: true });
16/*!
17 * @module common/operation
18 */
19const service_object_1 = require("./service-object");
20const util_1 = require("util");
21// eslint-disable-next-line @typescript-eslint/no-explicit-any
22class Operation extends service_object_1.ServiceObject {
23 /**
24 * An Operation object allows you to interact with APIs that take longer to
25 * process things.
26 *
27 * @constructor
28 * @alias module:common/operation
29 *
30 * @param {object} config - Configuration object.
31 * @param {module:common/service|module:common/serviceObject|module:common/grpcService|module:common/grpcServiceObject} config.parent - The parent object.
32 */
33 constructor(config) {
34 const methods = {
35 /**
36 * Checks to see if an operation exists.
37 */
38 exists: true,
39 /**
40 * Retrieves the operation.
41 */
42 get: true,
43 /**
44 * Retrieves metadata for the operation.
45 */
46 getMetadata: {
47 reqOpts: {
48 name: config.id,
49 },
50 },
51 };
52 config = Object.assign({
53 baseUrl: '',
54 }, config);
55 // eslint-disable-next-line @typescript-eslint/no-explicit-any
56 config.methods = (config.methods || methods);
57 super(config);
58 this.completeListeners = 0;
59 this.hasActiveListeners = false;
60 this.listenForEvents_();
61 }
62 /**
63 * Wraps the `complete` and `error` events in a Promise.
64 *
65 * @return {Promise}
66 */
67 promise() {
68 return new Promise((resolve, reject) => {
69 this.on('error', reject).on('complete', (metadata) => {
70 resolve([metadata]);
71 });
72 });
73 }
74 /**
75 * Begin listening for events on the operation. This method keeps track of how
76 * many "complete" listeners are registered and removed, making sure polling
77 * is handled automatically.
78 *
79 * As long as there is one active "complete" listener, the connection is open.
80 * When there are no more listeners, the polling stops.
81 *
82 * @private
83 */
84 listenForEvents_() {
85 this.on('newListener', (event) => {
86 if (event === 'complete') {
87 this.completeListeners++;
88 if (!this.hasActiveListeners) {
89 this.hasActiveListeners = true;
90 this.startPolling_();
91 }
92 }
93 });
94 this.on('removeListener', (event) => {
95 if (event === 'complete' && --this.completeListeners === 0) {
96 this.hasActiveListeners = false;
97 }
98 });
99 }
100 /**
101 * Poll for a status update. Returns null for an incomplete
102 * status, and metadata for a complete status.
103 *
104 * @private
105 */
106 poll_(callback) {
107 this.getMetadata((err, body) => {
108 if (err || body.error) {
109 callback(err || body.error);
110 return;
111 }
112 if (!body.done) {
113 callback(null);
114 return;
115 }
116 callback(null, body);
117 });
118 }
119 /**
120 * Poll `getMetadata` to check the operation's status. This runs a loop to
121 * ping the API on an interval.
122 *
123 * Note: This method is automatically called once a "complete" event handler
124 * is registered on the operation.
125 *
126 * @private
127 */
128 async startPolling_() {
129 if (!this.hasActiveListeners) {
130 return;
131 }
132 try {
133 const metadata = await util_1.promisify(this.poll_.bind(this))();
134 if (!metadata) {
135 setTimeout(this.startPolling_.bind(this), this.pollIntervalMs || 500);
136 return;
137 }
138 this.emit('complete', metadata);
139 }
140 catch (err) {
141 this.emit('error', err);
142 }
143 }
144}
145exports.Operation = Operation;
146//# sourceMappingURL=operation.js.map
\No newline at end of file