github.com/streamingfast/substreams@v1.6.2/cmd/substreams/service-utils.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  
     9  	"connectrpc.com/connect"
    10  	"github.com/spf13/cobra"
    11  	pbsinksvc "github.com/streamingfast/substreams/pb/sf/substreams/sink/service/v1"
    12  	"github.com/streamingfast/substreams/pb/sf/substreams/sink/service/v1/pbsinksvcconnect"
    13  )
    14  
    15  var fuzzyMatchPreferredStatusOrder = []pbsinksvc.DeploymentStatus{
    16  	pbsinksvc.DeploymentStatus_RUNNING,
    17  	pbsinksvc.DeploymentStatus_PAUSED,
    18  	pbsinksvc.DeploymentStatus_FAILING,
    19  	pbsinksvc.DeploymentStatus_STOPPED,
    20  	pbsinksvc.DeploymentStatus_UNKNOWN,
    21  }
    22  
    23  func fuzzyMatchDeployment(ctx context.Context, q string, cli pbsinksvcconnect.ProviderClient, cmd *cobra.Command, preferredStatusOrder []pbsinksvc.DeploymentStatus) (*pbsinksvc.DeploymentWithStatus, error) {
    24  	req := connect.NewRequest(&pbsinksvc.ListRequest{})
    25  	if err := addHeaders(cmd, req); err != nil {
    26  		return nil, err
    27  	}
    28  	resp, err := cli.List(ctx, req)
    29  	if err != nil {
    30  		return nil, fmt.Errorf("error fetching existing deployments: %w", err)
    31  	}
    32  
    33  	matching := make(map[*pbsinksvc.DeploymentWithStatus]pbsinksvc.DeploymentStatus)
    34  	for _, dep := range resp.Msg.Deployments {
    35  		if strings.HasPrefix(dep.Id, q) {
    36  			matching[dep] = dep.Status
    37  		}
    38  	}
    39  	if len(matching) == 0 {
    40  		return nil, fmt.Errorf("cannot find any deployment matching %q", q)
    41  	}
    42  	if len(matching) == 1 {
    43  		for k := range matching {
    44  			return k, nil
    45  		}
    46  	}
    47  	// more than one match, take the best status...
    48  
    49  	for i := len(preferredStatusOrder) - 1; i >= 0; i-- {
    50  		for k, v := range matching {
    51  			if v == preferredStatusOrder[i] {
    52  				delete(matching, k)
    53  			}
    54  		}
    55  		if len(matching) == 1 {
    56  			for k := range matching {
    57  				return k, nil
    58  			}
    59  		}
    60  		if len(matching) == 0 {
    61  			break
    62  		}
    63  	}
    64  	return nil, fmt.Errorf("cannot determine which deployment should match %q", q)
    65  }
    66  
    67  func printServices(outputs map[string]string) {
    68  	fmt.Printf("Services:\n")
    69  	var keys []string
    70  	for k := range outputs {
    71  		keys = append(keys, k)
    72  	}
    73  	sort.Strings(keys)
    74  
    75  	for _, k := range keys {
    76  		lines := strings.Split(outputs[k], "\n")
    77  		prefixLen := len(k) + 6
    78  		var withMargin string
    79  		for i, line := range lines {
    80  			if i == 0 {
    81  				withMargin = line + "\n"
    82  				continue
    83  			}
    84  			withMargin += strings.Repeat(" ", prefixLen) + line + "\n"
    85  		}
    86  		fmt.Printf("  - %s: %s", k, withMargin)
    87  	}
    88  
    89  }
    90  
    91  func userConfirm() bool {
    92  	var resp string
    93  	_, err := fmt.Scan(&resp)
    94  	if err != nil {
    95  		panic(err)
    96  	}
    97  
    98  	switch strings.ToLower(resp) {
    99  	case "y", "yes":
   100  		return true
   101  	}
   102  	return false
   103  }
   104  
   105  func interceptConnectionError(err error) error {
   106  	if connectError, ok := err.(*connect.Error); ok {
   107  		if connectError.Code() == connect.CodeUnavailable {
   108  			return fmt.Errorf("cannot connect to sink service: %w. Are you running `substreams alpha service serve` ?", err)
   109  		}
   110  	}
   111  	return err
   112  }