github.com/yandex/pandora@v0.5.32/components/providers/scenario/grpc/decode.go (about)

     1  package grpc
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	gun "github.com/yandex/pandora/components/guns/grpc/scenario"
     8  	"github.com/yandex/pandora/components/providers/scenario/config"
     9  	"github.com/yandex/pandora/components/providers/scenario/vs"
    10  	"github.com/yandex/pandora/lib/mp"
    11  )
    12  
    13  type IteratorIniter interface {
    14  	InitIterator(iter mp.Iterator)
    15  }
    16  
    17  func decodeAmmo(cfg *config.AmmoConfig, storage *vs.SourceStorage) ([]*gun.Scenario, error) {
    18  	callRegistry := make(map[string]config.CallConfig, len(cfg.Calls))
    19  	for _, req := range cfg.Calls {
    20  		callRegistry[req.Name] = req
    21  	}
    22  
    23  	scenarioRegistry := map[string]config.ScenarioConfig{}
    24  	for _, sc := range cfg.Scenarios {
    25  		scenarioRegistry[sc.Name] = sc
    26  	}
    27  
    28  	names, size := config.SpreadNames(cfg.Scenarios)
    29  	result := make([]*gun.Scenario, 0, size)
    30  	for _, sc := range cfg.Scenarios {
    31  		a, err := convertScenarioToAmmo(sc, callRegistry)
    32  		if err != nil {
    33  			return nil, fmt.Errorf("failed to convert scenario %s: %w", sc.Name, err)
    34  		}
    35  		a.VariableStorage = storage
    36  		ns, ok := names[sc.Name]
    37  		if !ok {
    38  			return nil, fmt.Errorf("scenario %s is not found", sc.Name)
    39  		}
    40  		for i := 0; i < ns; i++ {
    41  			result = append(result, a)
    42  		}
    43  	}
    44  
    45  	return result, nil
    46  }
    47  
    48  func convertScenarioToAmmo(sc config.ScenarioConfig, reqs map[string]config.CallConfig) (*gun.Scenario, error) {
    49  	iter := mp.NewNextIterator(time.Now().UnixNano())
    50  	result := &gun.Scenario{Name: sc.Name, MinWaitingTime: time.Millisecond * time.Duration(sc.MinWaitingTime)}
    51  	for _, sh := range sc.Requests {
    52  		name, cnt, sleep, err := config.ParseShootName(sh)
    53  		if err != nil {
    54  			return nil, fmt.Errorf("failed to parse shoot %s: %w", sh, err)
    55  		}
    56  		if name == "sleep" {
    57  			result.Calls[len(result.Calls)-1].Sleep += time.Millisecond * time.Duration(cnt)
    58  			continue
    59  		}
    60  		req, ok := reqs[name]
    61  		if !ok {
    62  			return nil, fmt.Errorf("request %s not found", name)
    63  		}
    64  		r := convertConfigToStep(req, iter)
    65  		if sleep > 0 {
    66  			r.Sleep += time.Millisecond * time.Duration(sleep)
    67  		}
    68  		for i := 0; i < cnt; i++ {
    69  			result.Calls = append(result.Calls, r)
    70  		}
    71  	}
    72  
    73  	return result, nil
    74  }
    75  
    76  func convertConfigToStep(req config.CallConfig, iter mp.Iterator) gun.Call {
    77  	postprocessors := make([]gun.Postprocessor, len(req.Postprocessors))
    78  	copy(postprocessors, req.Postprocessors)
    79  	preprocessors := make([]gun.Preprocessor, len(req.Preprocessors))
    80  	for i := range req.Preprocessors {
    81  		preprocessors[i] = req.Preprocessors[i]
    82  		if p, ok := preprocessors[i].(IteratorIniter); ok {
    83  			p.InitIterator(iter)
    84  		}
    85  	}
    86  	result := gun.Call{
    87  		Name:           req.Name,
    88  		Preprocessors:  preprocessors,
    89  		Postprocessors: postprocessors,
    90  		Tag:            req.Tag,
    91  		Call:           req.Call,
    92  		Metadata:       req.Metadata,
    93  		Payload:        []byte(req.Payload),
    94  	}
    95  
    96  	return result
    97  }