5
5
*/
6
6
7
7
import { v1 } from "@authzed/authzed-node" ;
8
- import { IClientCallMetrics , createClientCallMetricsInterceptor } from "@gitpod/gitpod-protocol/lib/util/grpc" ;
8
+ import { defaultGRPCOptions } from "@gitpod/gitpod-protocol/lib/util/grpc" ;
9
9
import { log } from "@gitpod/gitpod-protocol/lib/util/logging" ;
10
10
import * as grpc from "@grpc/grpc-js" ;
11
11
12
- export const SpiceDBClientProvider = Symbol ( "SpiceDBClientProvider" ) ;
13
-
14
12
export interface SpiceDBClientConfig {
15
13
address : string ;
16
14
token : string ;
17
15
}
18
16
19
17
export type SpiceDBClient = v1 . ZedPromiseClientInterface ;
20
18
type Client = v1 . ZedClientInterface & grpc . Client ;
21
- export interface SpiceDBClientProvider {
22
- getClient ( ) : SpiceDBClient ;
23
- }
24
19
25
20
export function spiceDBConfigFromEnv ( ) : SpiceDBClientConfig | undefined {
26
21
const token = process . env [ "SPICEDB_PRESHARED_KEY" ] ;
@@ -40,63 +35,41 @@ export function spiceDBConfigFromEnv(): SpiceDBClientConfig | undefined {
40
35
} ;
41
36
}
42
37
43
- function spicedbClientFromConfig ( config : SpiceDBClientConfig ) : Client {
44
- const clientOptions : grpc . ClientOptions = {
45
- "grpc.client_idle_timeout_ms" : 10000 , // this ensures a connection is not stuck in the "READY" state for too long. Required for the reconnect logic below.
46
- "grpc.max_reconnect_backoff_ms" : 5000 , // default: 12000
47
- } ;
48
-
49
- return v1 . NewClient (
50
- config . token ,
51
- config . address ,
52
- v1 . ClientSecurity . INSECURE_PLAINTEXT_CREDENTIALS ,
53
- undefined ,
54
- clientOptions ,
55
- ) as Client ;
56
- }
57
-
58
- export class CachingSpiceDBClientProvider implements SpiceDBClientProvider {
38
+ export class SpiceDBClientProvider {
59
39
private client : Client | undefined ;
60
40
61
- private readonly interceptors : grpc . Interceptor [ ] = [ ] ;
62
-
63
41
constructor (
64
- private readonly _clientConfig : SpiceDBClientConfig ,
65
- private readonly clientCallMetrics ?: IClientCallMetrics | undefined ,
66
- ) {
67
- if ( this . clientCallMetrics ) {
68
- this . interceptors . push ( createClientCallMetricsInterceptor ( this . clientCallMetrics ) ) ;
69
- }
70
- }
42
+ private readonly clientConfig : SpiceDBClientConfig ,
43
+ private readonly interceptors : grpc . Interceptor [ ] = [ ] ,
44
+ ) { }
71
45
72
46
getClient ( ) : SpiceDBClient {
73
- let client = this . client ;
74
- if ( ! client ) {
75
- client = spicedbClientFromConfig ( this . clientConfig ) ;
76
- } else if ( client . getChannel ( ) . getConnectivityState ( true ) !== grpc . connectivityState . READY ) {
77
- // (gpl): We need this check and explicit re-connect because we observe a ~120s connection timeout without it.
78
- // It's not entirely clear where that timeout comes from, but likely from the underlying transport, that is not exposed by grpc/grpc-js
79
- client . close ( ) ;
80
-
81
- log . warn ( "[spicedb] Lost connection to SpiceDB - reconnecting..." ) ;
82
-
83
- client = spicedbClientFromConfig ( this . clientConfig ) ;
47
+ if ( this . client ) {
48
+ const state = this . client . getChannel ( ) . getConnectivityState ( true ) ;
49
+ if ( state === grpc . connectivityState . TRANSIENT_FAILURE || state === grpc . connectivityState . SHUTDOWN ) {
50
+ log . warn ( "[spicedb] Lost connection to SpiceDB - reconnecting..." ) ;
51
+ try {
52
+ this . client . close ( ) ;
53
+ } catch ( error ) {
54
+ log . error ( "[spicedb] Failed to close client" , error ) ;
55
+ } finally {
56
+ this . client = undefined ;
57
+ }
58
+ }
84
59
}
85
- this . client = client ;
86
-
87
- return client . promises ;
88
- }
89
60
90
- protected get clientConfig ( ) {
91
- const config = this . _clientConfig ;
92
- if ( this . interceptors ) {
93
- return {
94
- ...config ,
95
- options : {
96
- interceptors : [ ...this . interceptors ] ,
61
+ if ( ! this . client ) {
62
+ this . client = v1 . NewClient (
63
+ this . clientConfig . token ,
64
+ this . clientConfig . address ,
65
+ v1 . ClientSecurity . INSECURE_PLAINTEXT_CREDENTIALS ,
66
+ undefined , //
67
+ {
68
+ ...defaultGRPCOptions ,
69
+ interceptors : this . interceptors ,
97
70
} ,
98
- } ;
71
+ ) as Client ;
99
72
}
100
- return config ;
73
+ return this . client . promises ;
101
74
}
102
75
}
0 commit comments