code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/oracle_spec.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 sqlstore
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  
    22  	"code.vegaprotocol.io/vega/datanode/entities"
    23  	"code.vegaprotocol.io/vega/datanode/metrics"
    24  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    25  
    26  	"github.com/georgysavva/scany/pgxscan"
    27  )
    28  
    29  type OracleSpec struct {
    30  	*ConnectionSource
    31  }
    32  
    33  var oracleSpecOrdering = TableOrdering{
    34  	ColumnOrdering{Name: "id", Sorting: ASC},
    35  	ColumnOrdering{Name: "vega_time", Sorting: ASC},
    36  }
    37  
    38  const (
    39  	sqlOracleSpecColumns = `id, created_at, updated_at, data, status, tx_hash, vega_time`
    40  )
    41  
    42  func NewOracleSpec(connectionSource *ConnectionSource) *OracleSpec {
    43  	return &OracleSpec{
    44  		ConnectionSource: connectionSource,
    45  	}
    46  }
    47  
    48  func (os *OracleSpec) Upsert(ctx context.Context, spec *entities.OracleSpec) error {
    49  	query := fmt.Sprintf(`insert into oracle_specs(%s)
    50  values ($1, $2, $3, $4, $5, $6, $7)
    51  on conflict (id, vega_time) do update
    52  set
    53  	created_at=EXCLUDED.created_at,
    54  	updated_at=EXCLUDED.updated_at,
    55  	data=EXCLUDED.data,
    56  	status=EXCLUDED.status,
    57  	tx_hash=EXCLUDED.tx_hash`, sqlOracleSpecColumns)
    58  
    59  	defer metrics.StartSQLQuery("OracleSpec", "Upsert")()
    60  	specData := spec.ExternalDataSourceSpec.Spec
    61  	if _, err := os.Exec(ctx, query, specData.ID, specData.CreatedAt, specData.UpdatedAt, specData.Data,
    62  		specData.Status, specData.TxHash, specData.VegaTime); err != nil {
    63  		return err
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  func (os *OracleSpec) GetSpecByID(ctx context.Context, specID string) (*entities.OracleSpec, error) {
    70  	defer metrics.StartSQLQuery("OracleSpec", "GetByID")()
    71  
    72  	var spec entities.DataSourceSpec
    73  	query := fmt.Sprintf(`%s
    74  where id = $1
    75  order by id, vega_time desc`, getOracleSpecsQuery())
    76  
    77  	err := pgxscan.Get(ctx, os.ConnectionSource, &spec, query, entities.SpecID(specID))
    78  	if err != nil {
    79  		return nil, os.wrapE(err)
    80  	}
    81  	return &entities.OracleSpec{
    82  		ExternalDataSourceSpec: &entities.ExternalDataSourceSpec{
    83  			Spec: &spec,
    84  		},
    85  	}, err
    86  }
    87  
    88  func (os *OracleSpec) GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.OracleSpec, error) {
    89  	defer metrics.StartSQLQuery("OracleSpec", "GetByTxHash")()
    90  
    91  	var specs []*entities.DataSourceSpec
    92  	query := "SELECT * FROM oracle_specs WHERE tx_hash = $1"
    93  	err := pgxscan.Select(ctx, os.ConnectionSource, &specs, query, txHash)
    94  	if err != nil {
    95  		return nil, os.wrapE(err)
    96  	}
    97  
    98  	oSpecs := []entities.OracleSpec{}
    99  	for _, spec := range specs {
   100  		oSpecs = append(oSpecs, entities.OracleSpec{ExternalDataSourceSpec: &entities.ExternalDataSourceSpec{Spec: spec}})
   101  	}
   102  
   103  	return oSpecs, err
   104  }
   105  
   106  func (os *OracleSpec) GetSpecsWithCursorPagination(ctx context.Context, specID string, pagination entities.CursorPagination) (
   107  	[]entities.OracleSpec, entities.PageInfo, error,
   108  ) {
   109  	if specID != "" {
   110  		return os.getSingleSpecWithPageInfo(ctx, specID)
   111  	}
   112  
   113  	return os.getSpecsWithPageInfo(ctx, pagination)
   114  }
   115  
   116  func (os *OracleSpec) getSingleSpecWithPageInfo(ctx context.Context, specID string) ([]entities.OracleSpec, entities.PageInfo, error) {
   117  	spec, err := os.GetSpecByID(ctx, specID)
   118  	if err != nil {
   119  		return nil, entities.PageInfo{}, err
   120  	}
   121  
   122  	return []entities.OracleSpec{*spec},
   123  		entities.PageInfo{
   124  			HasNextPage:     false,
   125  			HasPreviousPage: false,
   126  			StartCursor:     spec.Cursor().Encode(),
   127  			EndCursor:       spec.Cursor().Encode(),
   128  		}, nil
   129  }
   130  
   131  func (os *OracleSpec) getSpecsWithPageInfo(ctx context.Context, pagination entities.CursorPagination) (
   132  	[]entities.OracleSpec, entities.PageInfo, error,
   133  ) {
   134  	var (
   135  		specs    []entities.DataSourceSpec
   136  		oSpecs   = []entities.OracleSpec{}
   137  		pageInfo entities.PageInfo
   138  		err      error
   139  		args     []interface{}
   140  	)
   141  
   142  	query := getOracleSpecsQuery()
   143  	query, args, err = PaginateQuery[entities.DataSourceSpecCursor](query, args, oracleSpecOrdering, pagination)
   144  	if err != nil {
   145  		return nil, pageInfo, err
   146  	}
   147  
   148  	if err = pgxscan.Select(ctx, os.ConnectionSource, &specs, query, args...); err != nil {
   149  		return nil, pageInfo, fmt.Errorf("querying oracle specs: %w", err)
   150  	}
   151  
   152  	if len(specs) > 0 {
   153  		for i := range specs {
   154  			oSpecs = append(oSpecs, entities.OracleSpec{
   155  				ExternalDataSourceSpec: &entities.ExternalDataSourceSpec{
   156  					Spec: &specs[i],
   157  				},
   158  			})
   159  		}
   160  	}
   161  	oSpecs, pageInfo = entities.PageEntities[*v2.OracleSpecEdge](oSpecs, pagination)
   162  
   163  	return oSpecs, pageInfo, nil
   164  }
   165  
   166  func getOracleSpecsQuery() string {
   167  	return fmt.Sprintf(`select distinct on (id) %s
   168  from oracle_specs`, sqlOracleSpecColumns)
   169  }