UNPKG

3.63 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright 2019 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18Object.defineProperty(exports, "__esModule", { value: true });
19exports.DeadlineFilterFactory = exports.DeadlineFilter = void 0;
20const constants_1 = require("./constants");
21const filter_1 = require("./filter");
22const units = [
23 ['m', 1],
24 ['S', 1000],
25 ['M', 60 * 1000],
26 ['H', 60 * 60 * 1000],
27];
28function getDeadline(deadline) {
29 const now = new Date().getTime();
30 const timeoutMs = Math.max(deadline - now, 0);
31 for (const [unit, factor] of units) {
32 const amount = timeoutMs / factor;
33 if (amount < 1e8) {
34 return String(Math.ceil(amount)) + unit;
35 }
36 }
37 throw new Error('Deadline is too far in the future');
38}
39class DeadlineFilter extends filter_1.BaseFilter {
40 constructor(channel, callStream) {
41 super();
42 this.channel = channel;
43 this.callStream = callStream;
44 this.timer = null;
45 this.deadline = Infinity;
46 this.retreiveDeadline();
47 this.runTimer();
48 }
49 retreiveDeadline() {
50 const callDeadline = this.callStream.getDeadline();
51 if (callDeadline instanceof Date) {
52 this.deadline = callDeadline.getTime();
53 }
54 else {
55 this.deadline = callDeadline;
56 }
57 }
58 runTimer() {
59 var _a, _b;
60 if (this.timer) {
61 clearTimeout(this.timer);
62 }
63 const now = new Date().getTime();
64 const timeout = this.deadline - now;
65 if (timeout <= 0) {
66 process.nextTick(() => {
67 this.callStream.cancelWithStatus(constants_1.Status.DEADLINE_EXCEEDED, 'Deadline exceeded');
68 });
69 }
70 else if (this.deadline !== Infinity) {
71 this.timer = setTimeout(() => {
72 this.callStream.cancelWithStatus(constants_1.Status.DEADLINE_EXCEEDED, 'Deadline exceeded');
73 }, timeout);
74 (_b = (_a = this.timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
75 }
76 }
77 refresh() {
78 this.retreiveDeadline();
79 this.runTimer();
80 }
81 async sendMetadata(metadata) {
82 if (this.deadline === Infinity) {
83 return metadata;
84 }
85 /* The input metadata promise depends on the original channel.connect()
86 * promise, so when it is complete that implies that the channel is
87 * connected */
88 const finalMetadata = await metadata;
89 const timeoutString = getDeadline(this.deadline);
90 finalMetadata.set('grpc-timeout', timeoutString);
91 return finalMetadata;
92 }
93 receiveTrailers(status) {
94 if (this.timer) {
95 clearTimeout(this.timer);
96 }
97 return status;
98 }
99}
100exports.DeadlineFilter = DeadlineFilter;
101class DeadlineFilterFactory {
102 constructor(channel) {
103 this.channel = channel;
104 }
105 createFilter(callStream) {
106 return new DeadlineFilter(this.channel, callStream);
107 }
108}
109exports.DeadlineFilterFactory = DeadlineFilterFactory;
110//# sourceMappingURL=deadline-filter.js.map
\No newline at end of file