Skip to content

Commit ba08267

Browse files
authored
Merge pull request #2352 from murgatroid99/grpc-js_deadline_refinement
grpc-js: Improve timeout handling and deadline logging
2 parents 7ab5368 + 37eb5ed commit ba08267

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

packages/grpc-js/src/deadline.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,45 @@ export function getDeadlineTimeoutString(deadline: Deadline) {
5151
throw new Error('Deadline is too far in the future')
5252
}
5353

54+
/**
55+
* See https://nodejs.org/api/timers.html#settimeoutcallback-delay-args
56+
* In particular, "When delay is larger than 2147483647 or less than 1, the
57+
* delay will be set to 1. Non-integer delays are truncated to an integer."
58+
* This number of milliseconds is almost 25 days.
59+
*/
60+
const MAX_TIMEOUT_TIME = 2147483647;
61+
62+
/**
63+
* Get the timeout value that should be passed to setTimeout now for the timer
64+
* to end at the deadline. For any deadline before now, the timer should end
65+
* immediately, represented by a value of 0. For any deadline more than
66+
* MAX_TIMEOUT_TIME milliseconds in the future, a timer cannot be set that will
67+
* end at that time, so it is treated as infinitely far in the future.
68+
* @param deadline
69+
* @returns
70+
*/
5471
export function getRelativeTimeout(deadline: Deadline) {
5572
const deadlineMs = deadline instanceof Date ? deadline.getTime() : deadline;
5673
const now = new Date().getTime();
57-
return deadlineMs - now;
74+
const timeout = deadlineMs - now;
75+
if (timeout < 0) {
76+
return 0;
77+
} else if (timeout > MAX_TIMEOUT_TIME) {
78+
return Infinity
79+
} else {
80+
return timeout;
81+
}
82+
}
83+
84+
export function deadlineToString(deadline: Deadline): string {
85+
if (deadline instanceof Date) {
86+
return deadline.toISOString();
87+
} else {
88+
const dateDeadline = new Date(deadline);
89+
if (Number.isNaN(dateDeadline.getTime())) {
90+
return '' + deadline;
91+
} else {
92+
return dateDeadline.toISOString();
93+
}
94+
}
5895
}

packages/grpc-js/src/internal-channel.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import { LoadBalancingCall } from './load-balancing-call';
4646
import { CallCredentials } from './call-credentials';
4747
import { Call, CallStreamOptions, InterceptingListener, MessageContext, StatusObject } from './call-interface';
4848
import { SubchannelCall } from './subchannel-call';
49-
import { Deadline, getDeadlineTimeoutString } from './deadline';
49+
import { Deadline, deadlineToString, getDeadlineTimeoutString } from './deadline';
5050
import { ResolvingCall } from './resolving-call';
5151
import { getNextCallNumber } from './call-number';
5252
import { restrictControlPlaneStatusCode } from './control-plane-status';
@@ -469,7 +469,7 @@ export class InternalChannel {
469469
'] method="' +
470470
method +
471471
'", deadline=' +
472-
deadline
472+
deadlineToString(deadline)
473473
);
474474
const finalOptions: CallStreamOptions = {
475475
deadline: deadline,

packages/grpc-js/src/resolving-call.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import { CallCredentials } from "./call-credentials";
1919
import { Call, CallStreamOptions, InterceptingListener, MessageContext, StatusObject } from "./call-interface";
2020
import { LogVerbosity, Propagate, Status } from "./constants";
21-
import { Deadline, getDeadlineTimeoutString, getRelativeTimeout, minDeadline } from "./deadline";
21+
import { Deadline, deadlineToString, getDeadlineTimeoutString, getRelativeTimeout, minDeadline } from "./deadline";
2222
import { FilterStack, FilterStackFactory } from "./filter-stack";
2323
import { InternalChannel } from "./internal-channel";
2424
import { Metadata } from "./metadata";
@@ -79,9 +79,9 @@ export class ResolvingCall implements Call {
7979

8080
private runDeadlineTimer() {
8181
clearTimeout(this.deadlineTimer);
82-
this.trace('Deadline: ' + this.deadline);
83-
if (this.deadline !== Infinity) {
84-
const timeout = getRelativeTimeout(this.deadline);
82+
this.trace('Deadline: ' + deadlineToString(this.deadline));
83+
const timeout = getRelativeTimeout(this.deadline);
84+
if (timeout !== Infinity) {
8585
this.trace('Deadline will be reached in ' + timeout + 'ms');
8686
const handleDeadline = () => {
8787
this.cancelWithStatus(

0 commit comments

Comments
 (0)