Skip to content

Commit aa59d72

Browse files
authored
feat(client): Add utility functions isGrpcDeadlineError and isGrpcCancelledError (#1548)
1 parent e084565 commit aa59d72

File tree

6 files changed

+45
-11
lines changed

6 files changed

+45
-11
lines changed

packages/client/src/base-client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export class BaseClient {
7373
*
7474
* The deadline is a point in time after which any pending gRPC request will be considered as failed;
7575
* this will locally result in the request call throwing a {@link _grpc.ServiceError|ServiceError}
76-
* with code {@link _grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}.
76+
* with code {@link _grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}; see {@link isGrpcDeadlineError}.
7777
*
7878
* It is stronly recommended to explicitly set deadlines. If no deadline is set, then it is
7979
* possible for the client to end up waiting forever for a response.
@@ -93,7 +93,7 @@ export class BaseClient {
9393
/**
9494
* Set an {@link AbortSignal} that, when aborted, cancels any ongoing service requests executed in
9595
* `fn`'s scope. This will locally result in the request call throwing a {@link _grpc.ServiceError|ServiceError}
96-
* with code {@link _grpc.status.CANCELLED|CANCELLED}.
96+
* with code {@link _grpc.status.CANCELLED|CANCELLED}; see {@link isGrpcCancelledError}.
9797
*
9898
* This method is only a convenience wrapper around {@link Connection.withAbortSignal}.
9999
*

packages/client/src/connection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ export class Connection {
471471
*
472472
* The deadline is a point in time after which any pending gRPC request will be considered as failed;
473473
* this will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
474-
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}.
474+
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}; see {@link isGrpcDeadlineError}.
475475
*
476476
* It is stronly recommended to explicitly set deadlines. If no deadline is set, then it is
477477
* possible for the client to end up waiting forever for a response.
@@ -490,7 +490,7 @@ export class Connection {
490490
/**
491491
* Set an {@link AbortSignal} that, when aborted, cancels any ongoing service requests executed in
492492
* `fn`'s scope. This will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
493-
* with code {@link grpc.status.CANCELLED|CANCELLED}.
493+
* with code {@link grpc.status.CANCELLED|CANCELLED}; see {@link isGrpcCancelledError}.
494494
*
495495
* This method is only a convenience wrapper around {@link Connection.withAbortSignal}.
496496
*

packages/client/src/errors.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ServiceError as GrpcServiceError } from '@grpc/grpc-js';
1+
import { ServiceError as GrpcServiceError, status } from '@grpc/grpc-js';
22
import { RetryState, TemporalFailure } from '@temporalio/common';
33
import { isError, isRecord, SymbolBasedInstanceOfError } from '@temporalio/common/lib/type-helpers';
44

@@ -79,6 +79,9 @@ export class WorkflowContinuedAsNewError extends Error {
7979
}
8080
}
8181

82+
/**
83+
* Returns true if the provided error is a {@link GrpcServiceError}.
84+
*/
8285
export function isGrpcServiceError(err: unknown): err is GrpcServiceError {
8386
return (
8487
isError(err) &&
@@ -87,6 +90,36 @@ export function isGrpcServiceError(err: unknown): err is GrpcServiceError {
8790
);
8891
}
8992

93+
/**
94+
* Returns true if the provided error or its cause is a {@link GrpcServiceError} with code DEADLINE_EXCEEDED.
95+
*
96+
* @see {@link Connection.withDeadline}
97+
*/
98+
export function isGrpcDeadlineError(err: unknown): err is Error {
99+
while (isError(err)) {
100+
if (isGrpcServiceError(err) && (err as GrpcServiceError).code === status.DEADLINE_EXCEEDED) {
101+
return true;
102+
}
103+
err = (err as any).cause;
104+
}
105+
return false;
106+
}
107+
108+
/**
109+
* Returns true if the provided error or its cause is a {@link GrpcServiceError} with code CANCELLED.
110+
*
111+
* @see {@link Connection.withAbortSignal}
112+
*/
113+
export function isGrpcCancelledError(err: unknown): err is Error {
114+
while (isError(err)) {
115+
if (isGrpcServiceError(err) && (err as GrpcServiceError).code === status.CANCELLED) {
116+
return true;
117+
}
118+
err = (err as any).cause;
119+
}
120+
return false;
121+
}
122+
90123
/**
91124
* @deprecated Use `isGrpcServiceError` instead
92125
*/

packages/client/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export interface ConnectionLike {
102102
*
103103
* The deadline is a point in time after which any pending gRPC request will be considered as failed;
104104
* this will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
105-
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}.
105+
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}; see {@link isGrpcDeadlineError}.
106106
*
107107
* It is stronly recommended to explicitly set deadlines. If no deadline is set, then it is
108108
* possible for the client to end up waiting forever for a response.
@@ -127,7 +127,7 @@ export interface ConnectionLike {
127127
/**
128128
* Set an {@link AbortSignal} that, when aborted, cancels any ongoing service requests executed in
129129
* `fn`'s scope. This will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
130-
* with code {@link grpc.status.CANCELLED|CANCELLED}.
130+
* with code {@link grpc.status.CANCELLED|CANCELLED}; see {@link isGrpcCancelledError}.
131131
*
132132
* @returns value returned from `fn`
133133
*

packages/cloud/src/cloud-operations-client.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class CloudOperationsClient {
5959
*
6060
* The deadline is a point in time after which any pending gRPC request will be considered as failed;
6161
* this will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
62-
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}.
62+
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}; see {@link isGrpcDeadlineError}.
6363
*
6464
* It is stronly recommended to explicitly set deadlines. If no deadline is set, then it is
6565
* possible for the client to end up waiting forever for a response.
@@ -80,7 +80,7 @@ export class CloudOperationsClient {
8080
/**
8181
* Set an {@link AbortSignal} that, when aborted, cancels any ongoing service requests executed in
8282
* `fn`'s scope. This will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
83-
* with code {@link grpc.status.CANCELLED|CANCELLED}.
83+
* with code {@link grpc.status.CANCELLED|CANCELLED}; see {@link isGrpcCancelledError}.
8484
*
8585
* This method is only a convenience wrapper around {@link CloudOperationsConnection.withAbortSignal}.
8686
*
@@ -468,7 +468,7 @@ export class CloudOperationsConnection {
468468
*
469469
* The deadline is a point in time after which any pending gRPC request will be considered as failed;
470470
* this will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
471-
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}.
471+
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}; see {@link isGrpcDeadlineError}.
472472
*
473473
* It is stronly recommended to explicitly set deadlines. If no deadline is set, then it is
474474
* possible for the client to end up waiting forever for a response.

packages/test/src/test-client-connection.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
Client,
1111
Connection,
1212
defaultGrpcRetryOptions,
13+
isGrpcCancelledError,
1314
isGrpcServiceError,
1415
isRetryableError,
1516
makeGrpcRetryInterceptor,
@@ -123,7 +124,7 @@ test('withMetadata / withDeadline / withAbortSignal set the CallContext for RPC
123124
const ctrl = new AbortController();
124125
setTimeout(() => ctrl.abort(), 10);
125126
const err = await t.throwsAsync(conn.withAbortSignal(ctrl.signal, () => conn.workflowService.updateNamespace({})));
126-
t.true(isGrpcServiceError(err) && err.code === grpc.status.CANCELLED);
127+
t.true(isGrpcCancelledError(err));
127128
});
128129

129130
test('Connection can connect using "[ipv6]:port" address', async (t) => {

0 commit comments

Comments
 (0)