// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: Apache-2.0 package arvadosclient import ( "sync" "git.arvados.org/arvados.git/sdk/go/arvados" ) // A ClientPool is a pool of ArvadosClients. This is useful for // applications that make API calls using a dynamic set of tokens, // like web services that pass through their own clients' // credentials. See arvados-git-httpd for an example, and sync.Pool // for more information about garbage collection. type ClientPool struct { // Initialize new clients by copying this one. Prototype *ArvadosClient pool *sync.Pool lastErr error setupOnce sync.Once } // MakeClientPool returns a new empty ClientPool, using environment // variables to initialize the prototype. func MakeClientPool() *ClientPool { return MakeClientPoolWith(nil) } // MakeClientPoolWith returns a new empty ClientPool with a previously // initialized arvados.Client. func MakeClientPoolWith(client *arvados.Client) *ClientPool { var err error var proto *ArvadosClient if client == nil { proto, err = MakeArvadosClient() } else { proto, err = New(client) } return &ClientPool{ Prototype: proto, lastErr: err, } } func (p *ClientPool) setup() { p.pool = &sync.Pool{New: func() interface{} { if p.lastErr != nil { return nil } c := *p.Prototype return &c }} } // Err returns the error that was encountered last time Get returned // nil. func (p *ClientPool) Err() error { return p.lastErr } // Get returns an ArvadosClient taken from the pool, or a new one if // the pool is empty. If an existing client is returned, its state // (including its ApiToken) will be just as it was when it was Put // back in the pool. func (p *ClientPool) Get() *ArvadosClient { p.setupOnce.Do(p.setup) c, ok := p.pool.Get().(*ArvadosClient) if !ok { return nil } return c } // Put puts an ArvadosClient back in the pool. func (p *ClientPool) Put(c *ArvadosClient) { p.setupOnce.Do(p.setup) p.pool.Put(c) }