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 }