You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The zitadel-go client in pkg/client/client.go is basically a wrapper that offers access to multiple (generated) gRPC clients. Unlike the individual gRPC clients themselves, this client is not safe for concurrent use, though, as its methods are structured like this:
Since the access to the systemService field is not guarded by a mutex, this code could lead to race conditions.
That's a pity because it's useful to have just a single client instance in your code and to reuse it in different goroutines. That way you only need to create a single gRPC connection (for example, I use this heavily in tests where I instantiate the client once at the beginning of the outer test and use it in all, possibly parallel, subtests - here the Go race detector immediately fires right now).
Possible solutions
Guarding the above call with a mutex is probably too costly in the most common case. I've experimented with an alternative solution that doesn't "lazy-initialize" the individual service clients but initializes them all at once (1085e72). Since the only line of code executed by the New...ServiceClient(c.connection) calls is return &systemServiceClient{cc}, the impact of this shouldn't be too big.
If performance of the constructor is a concern, though, having an option you can provide to the constructor to pre-initialize all service clients could then be an alternative (72724b5).
The text was updated successfully, but these errors were encountered:
Background
The zitadel-go client in
pkg/client/client.go
is basically a wrapper that offers access to multiple (generated) gRPC clients. Unlike the individual gRPC clients themselves, this client is not safe for concurrent use, though, as its methods are structured like this:Since the access to the
systemService
field is not guarded by a mutex, this code could lead to race conditions.That's a pity because it's useful to have just a single client instance in your code and to reuse it in different goroutines. That way you only need to create a single gRPC connection (for example, I use this heavily in tests where I instantiate the client once at the beginning of the outer test and use it in all, possibly parallel, subtests - here the Go race detector immediately fires right now).
Possible solutions
Guarding the above call with a mutex is probably too costly in the most common case. I've experimented with an alternative solution that doesn't "lazy-initialize" the individual service clients but initializes them all at once (1085e72). Since the only line of code executed by the
New...ServiceClient(c.connection)
calls isreturn &systemServiceClient{cc}
, the impact of this shouldn't be too big.If performance of the constructor is a concern, though, having an option you can provide to the constructor to pre-initialize all service clients could then be an alternative (72724b5).
The text was updated successfully, but these errors were encountered: