code.vegaprotocol.io/vega@v0.79.0/core/coreapi/services/assets.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package services
    17  
    18  import (
    19  	"context"
    20  	"sync"
    21  
    22  	"code.vegaprotocol.io/vega/core/events"
    23  	"code.vegaprotocol.io/vega/core/subscribers"
    24  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    25  )
    26  
    27  type assetE interface {
    28  	events.Event
    29  	Asset() vegapb.Asset
    30  }
    31  
    32  type Assets struct {
    33  	*subscribers.Base
    34  	ctx context.Context
    35  
    36  	mu     sync.RWMutex
    37  	assets map[string]vegapb.Asset
    38  	ch     chan vegapb.Asset
    39  }
    40  
    41  func NewAssets(ctx context.Context) (assets *Assets) {
    42  	defer func() { go assets.consume() }()
    43  	return &Assets{
    44  		Base:   subscribers.NewBase(ctx, 1000, true),
    45  		ctx:    ctx,
    46  		assets: map[string]vegapb.Asset{},
    47  		ch:     make(chan vegapb.Asset, 100),
    48  	}
    49  }
    50  
    51  func (a *Assets) consume() {
    52  	defer func() { close(a.ch) }()
    53  	for {
    54  		select {
    55  		case <-a.Closed():
    56  			return
    57  		case asset, ok := <-a.ch:
    58  			if !ok {
    59  				// cleanup base
    60  				a.Halt()
    61  				// channel is closed
    62  				return
    63  			}
    64  			a.mu.Lock()
    65  			a.assets[asset.Id] = asset
    66  			a.mu.Unlock()
    67  		}
    68  	}
    69  }
    70  
    71  func (a *Assets) Push(evts ...events.Event) {
    72  	for _, e := range evts {
    73  		if ae, ok := e.(assetE); ok {
    74  			a.ch <- ae.Asset()
    75  		}
    76  	}
    77  }
    78  
    79  func (a *Assets) List(assetID string) []*vegapb.Asset {
    80  	a.mu.RLock()
    81  	defer a.mu.RUnlock()
    82  	if len(assetID) > 0 {
    83  		return a.getAsset(assetID)
    84  	}
    85  	return a.getAllAssets()
    86  }
    87  
    88  func (a *Assets) getAsset(assetID string) []*vegapb.Asset {
    89  	out := []*vegapb.Asset{}
    90  	asset, ok := a.assets[assetID]
    91  	if ok {
    92  		out = append(out, &asset)
    93  	}
    94  	return out
    95  }
    96  
    97  func (a *Assets) getAllAssets() []*vegapb.Asset {
    98  	out := make([]*vegapb.Asset, 0, len(a.assets))
    99  	for _, v := range a.assets {
   100  		v := v
   101  		out = append(out, &v)
   102  	}
   103  	return out
   104  }
   105  
   106  func (a *Assets) Types() []events.Type {
   107  	return []events.Type{
   108  		events.AssetEvent,
   109  	}
   110  }