| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "context" |
| "net/http" |
| "sync" |
| |
| buildbucketpb "go.chromium.org/luci/buildbucket/proto" |
| gerritpb "go.chromium.org/luci/common/proto/gerrit" |
| |
| "go.fuchsia.dev/infra/gerrit" |
| ) |
| |
| // gerritClientKey is the key by which gerrit.Client structs are hashed in the |
| // gerritMultiClient cache. |
| type gerritClientKey struct { |
| hostname string |
| project string |
| } |
| |
| // gerritMultiClient implements a wrapper around multiple per-project gerrit |
| // clients, as the gerrit.Client struct is scoped to a single repository. |
| type gerritMultiClient struct { |
| authClient *http.Client |
| clients map[gerritClientKey]*gerrit.Client |
| // Protects access to the `clients` map. |
| mu sync.Mutex |
| } |
| |
| func (c *gerritMultiClient) getChange( |
| ctx context.Context, |
| change *buildbucketpb.GerritChange, |
| opts ...gerritpb.QueryOption, |
| ) (*gerritpb.ChangeInfo, error) { |
| client, err := c.clientForProject(change.Host, change.Project) |
| if err != nil { |
| return nil, err |
| } |
| return client.GetChange(ctx, change.Change, opts...) |
| } |
| |
| func (c *gerritMultiClient) clientForProject(hostname, project string) (*gerrit.Client, error) { |
| key := gerritClientKey{hostname: hostname, project: project} |
| c.mu.Lock() |
| defer c.mu.Unlock() |
| if client, ok := c.clients[key]; ok { |
| return client, nil |
| } |
| client, err := gerrit.NewClient(hostname, project, c.authClient) |
| if err != nil { |
| return nil, err |
| } |
| c.clients[key] = client |
| return client, nil |
| } |