@@ -12,6 +12,8 @@ import { getExperimentsClientForBackend } from "@gitpod/gitpod-protocol/lib/expe
12
12
import { inject , injectable } from "inversify" ;
13
13
import { observeSpicedbClientLatency , spicedbClientLatency } from "../prometheus-metrics" ;
14
14
import { SpiceDBClient } from "./spicedb" ;
15
+ // TODO(gpl) Change to "@grpc/grpc-js" once we can use 1.9.0 (or higher) everywhere
16
+ import * as grpc from "@grpc/grpc-js_1_9_0" ;
15
17
16
18
@injectable ( )
17
19
export class SpiceDBAuthorizer {
@@ -43,7 +45,7 @@ export class SpiceDBAuthorizer {
43
45
const timer = spicedbClientLatency . startTimer ( ) ;
44
46
let error : Error | undefined ;
45
47
try {
46
- const response = await timeout ( this . client . checkPermission ( req ) , 5000 ) ;
48
+ const response = await this . client . checkPermission ( req , this . callOptions ) ;
47
49
const permitted = response . permissionship === v1 . CheckPermissionResponse_Permissionship . HAS_PERMISSION ;
48
50
49
51
return permitted ;
@@ -68,13 +70,11 @@ export class SpiceDBAuthorizer {
68
70
const timer = spicedbClientLatency . startTimer ( ) ;
69
71
let error : Error | undefined ;
70
72
try {
71
- const response = await timeout (
72
- this . client . writeRelationships (
73
- v1 . WriteRelationshipsRequest . create ( {
74
- updates,
75
- } ) ,
76
- ) ,
77
- 5000 ,
73
+ const response = await this . client . writeRelationships (
74
+ v1 . WriteRelationshipsRequest . create ( {
75
+ updates,
76
+ } ) ,
77
+ this . callOptions ,
78
78
) ;
79
79
log . info ( "[spicedb] Successfully wrote relationships." , { response, updates } ) ;
80
80
@@ -98,25 +98,20 @@ export class SpiceDBAuthorizer {
98
98
const timer = spicedbClientLatency . startTimer ( ) ;
99
99
let error : Error | undefined ;
100
100
try {
101
- return await timeout (
102
- ( async ( ) => {
103
- const existing = await client . readRelationships ( v1 . ReadRelationshipsRequest . create ( req ) ) ;
104
- if ( existing . length > 0 ) {
105
- const response = await client . deleteRelationships ( req ) ;
106
- const after = await client . readRelationships ( v1 . ReadRelationshipsRequest . create ( req ) ) ;
107
- if ( after . length > 0 ) {
108
- log . error ( "[spicedb] Failed to delete relationships." , { existing, after, request : req } ) ;
109
- }
110
- log . info ( `[spicedb] Successfully deleted ${ existing . length } relationships.` , {
111
- response,
112
- request : req ,
113
- existing,
114
- } ) ;
115
- }
116
- return existing ;
117
- } ) ( ) ,
118
- 5000 ,
119
- ) ;
101
+ const existing = await client . readRelationships ( v1 . ReadRelationshipsRequest . create ( req ) , this . callOptions ) ;
102
+ if ( existing . length > 0 ) {
103
+ const response = await client . deleteRelationships ( req , this . callOptions ) ;
104
+ const after = await client . readRelationships ( v1 . ReadRelationshipsRequest . create ( req ) , this . callOptions ) ;
105
+ if ( after . length > 0 ) {
106
+ log . error ( "[spicedb] Failed to delete relationships." , { existing, after, request : req } ) ;
107
+ }
108
+ log . info ( `[spicedb] Successfully deleted ${ existing . length } relationships.` , {
109
+ response,
110
+ request : req ,
111
+ existing,
112
+ } ) ;
113
+ }
114
+ return existing ;
120
115
} catch ( err ) {
121
116
error = err ;
122
117
// While in we're running two authorization systems in parallel, we do not hard fail on writes.
@@ -133,7 +128,18 @@ export class SpiceDBAuthorizer {
133
128
if ( ! this . client ) {
134
129
return [ ] ;
135
130
}
136
- return this . client . readRelationships ( req ) ;
131
+ return this . client . readRelationships ( req , this . callOptions ) ;
132
+ }
133
+
134
+ /**
135
+ * permission_service.grpc-client.d.ts has all methods overloaded with this pattern:
136
+ * - xyzRelationships(input: Request, metadata?: grpc.Metadata | grpc.CallOptions, options?: grpc.CallOptions): grpc.ClientReadableStream<ReadRelationshipsResponse>;
137
+ * But the promisified client somehow does not have the same overloads. Thus we convince it here that options may be passed as 2nd argument.
138
+ */
139
+ private get callOptions ( ) : grpc . Metadata {
140
+ return {
141
+ deadline : Date . now ( ) + 5000 ,
142
+ } as any as grpc . Metadata ;
137
143
}
138
144
}
139
145
function startTimer ( ) {
@@ -146,20 +152,20 @@ function stopTimer(method: string, hrtime: [number, number]) {
146
152
log . info ( `[SPICEDB] ${ method } (${ ms } ms)` ) ;
147
153
}
148
154
149
- async function timeout < T > ( code : Promise < T > , ms : number ) : Promise < T > {
150
- return new Promise < T > ( ( resolve , reject ) => {
151
- const timer = setTimeout ( ( ) => {
152
- reject ( new Error ( `[spicedb] timed out after ${ ms } ms` ) ) ;
153
- } , ms ) ;
154
- code . then (
155
- ( res ) => {
156
- clearTimeout ( timer ) ;
157
- resolve ( res ) ;
158
- } ,
159
- ( err ) => {
160
- clearTimeout ( timer ) ;
161
- reject ( err ) ;
162
- } ,
163
- ) ;
164
- } ) ;
165
- }
155
+ // async function timeout<T>(code: Promise<T>, ms: number): Promise<T> {
156
+ // return new Promise<T>((resolve, reject) => {
157
+ // const timer = setTimeout(() => {
158
+ // reject(new Error(`[spicedb] timed out after ${ms}ms`));
159
+ // }, ms);
160
+ // code.then(
161
+ // (res) => {
162
+ // clearTimeout(timer);
163
+ // resolve(res);
164
+ // },
165
+ // (err) => {
166
+ // clearTimeout(timer);
167
+ // reject(err);
168
+ // },
169
+ // );
170
+ // });
171
+ // }
0 commit comments