@@ -31,12 +31,14 @@ import (
31
31
)
32
32
33
33
type ReplayCmd struct {
34
- client * sdk.Client
35
- from flags.TimeValue
36
- configPaths []string
37
- sloName string
38
- project string
39
- deleteAll bool
34
+ client * sdk.Client
35
+ from TimeValue
36
+ from flags.TimeValue
37
+ configPaths []string
38
+ sloName string
39
+ project string
40
+ deleteAll bool
41
+ playlistsAvailable bool
40
42
}
41
43
42
44
//go:embed replay_example.sh
@@ -79,6 +81,7 @@ func (r *ReplayCmd) Run(cmd *cobra.Command) error {
79
81
if r .client .Config .Project == "*" {
80
82
return errProjectWildcardIsNotAllowed
81
83
}
84
+ r .arePlaylistEnabled (cmd .Context ())
82
85
replays , err := r .prepareConfigs ()
83
86
if err != nil {
84
87
return err
@@ -92,9 +95,7 @@ func (r *ReplayCmd) RunReplays(cmd *cobra.Command, replays []ReplayConfig) (fail
92
95
return 0 , err
93
96
}
94
97
95
- arePlaylistEnabled := r .arePlaylistEnabled (cmd .Context ())
96
-
97
- if arePlaylistEnabled {
98
+ if r .playlistsAvailable {
98
99
cmd .Println (colorstring .Color ("[yellow]- Your organization has access to Replay queues!" ))
99
100
cmd .Println (colorstring .Color ("[yellow]- To learn more about Replay queues, follow this link: " +
100
101
"https://docs.nobl9.com/replay-canary/ [reset]" ))
@@ -107,7 +108,7 @@ func (r *ReplayCmd) RunReplays(cmd *cobra.Command, replays []ReplayConfig) (fail
107
108
i + 1 , len (replays ), replay .SLO , replay .Project ,
108
109
replay .From .Format (flags .TimeLayout ), time .Now ().In (replay .From .Location ()).Format (flags .TimeLayout ))))
109
110
110
- if arePlaylistEnabled {
111
+ if r . playlistsAvailable {
111
112
cmd .Println ("Replay is added to the queue..." )
112
113
err = r .runReplay (cmd .Context (), replay )
113
114
@@ -137,7 +138,12 @@ func (r *ReplayCmd) RunReplays(cmd *cobra.Command, replays []ReplayConfig) (fail
137
138
return len (failedIndexes ), nil
138
139
}
139
140
140
- func (r * ReplayCmd ) arePlaylistEnabled (ctx context.Context ) bool {
141
+ type PlaylistConfiguration struct {
142
+ EnabledPlaylists bool `json:"enabledPlaylists"`
143
+ }
144
+
145
+ func (r * ReplayCmd ) arePlaylistEnabled (ctx context.Context ) {
146
+ r .playlistsAvailable = true
141
147
data , _ , err := r .doRequest (
142
148
ctx ,
143
149
http .MethodGet ,
@@ -146,17 +152,13 @@ func (r *ReplayCmd) arePlaylistEnabled(ctx context.Context) bool {
146
152
nil ,
147
153
nil )
148
154
if err != nil {
149
- return true
155
+ fmt . Printf ( "error checking playlist availability: %v \n " , err )
150
156
}
151
157
var pc PlaylistConfiguration
152
158
if err = json .Unmarshal (data , & pc ); err != nil {
153
- return true
159
+ fmt . Printf ( "error unmarshalling playlist configuration: %v \n " , err )
154
160
}
155
- return pc .EnabledPlaylists
156
- }
157
-
158
- type PlaylistConfiguration struct {
159
- EnabledPlaylists bool `json:"enabledPlaylists"`
161
+ r .playlistsAvailable = pc .EnabledPlaylists
160
162
}
161
163
162
164
type ReplayConfig struct {
@@ -325,16 +327,28 @@ outer:
325
327
}
326
328
327
329
// Check Replay availability.
330
+ if err := r .checkReplayAvailability (ctx , replays ); err != nil {
331
+ return err
332
+ }
333
+
334
+ return nil
335
+ }
336
+
337
+ func (r * ReplayCmd ) checkReplayAvailability (ctx context.Context , replays []ReplayConfig ) error {
328
338
notAvailable := make ([]string , 0 )
329
339
mu := sync.Mutex {}
330
340
eg , ctx := errgroup .WithContext (ctx )
331
341
eg .SetLimit (10 )
342
+
332
343
for i := range replays {
333
344
eg .Go (func () error {
334
345
c := replays [i ]
335
346
timeNow := time .Now ()
336
347
tt := c .ToReplay (timeNow )
337
- offset := i * int (averageReplayDuration .Minutes ())
348
+ offset := 0
349
+ if ! r .playlistsAvailable {
350
+ offset = i * int (averageReplayDuration .Minutes ())
351
+ }
338
352
expectedDuration := offset + tt .Duration .Value
339
353
av , err := r .getReplayAvailability (ctx , c , tt .Duration .Unit , expectedDuration )
340
354
if err != nil {
@@ -343,6 +357,7 @@ outer:
343
357
}
344
358
if ! av .Available {
345
359
mu .Lock ()
360
+ defer mu .Unlock ()
346
361
notAvailable = append (notAvailable ,
347
362
fmt .Sprintf ("['%s' SLO in '%s' Project] %s" ,
348
363
c .SLO , c .Project , r .replayUnavailabilityReasonExplanation (
@@ -351,18 +366,20 @@ outer:
351
366
time .Duration (expectedDuration )* time .Minute ,
352
367
time .Duration (offset )* time .Minute ,
353
368
timeNow )))
354
- mu .Unlock ()
355
369
}
356
370
return nil
357
371
})
358
372
}
359
- if err = eg .Wait (); err != nil {
373
+
374
+ if err := eg .Wait (); err != nil {
360
375
return err
361
376
}
377
+
362
378
if len (notAvailable ) > 0 {
363
379
return errors .Errorf ("The following SLOs are not available for Replay: \n - %s" ,
364
380
strings .Join (notAvailable , "\n - " ))
365
381
}
382
+
366
383
return nil
367
384
}
368
385
@@ -522,7 +539,7 @@ func (r *ReplayCmd) replayUnavailabilityReasonExplanation(
522
539
" + %dm (start offset to ensure Replay covers the desired time window) %s." +
523
540
" Edit the Data Source and run Replay once again." ,
524
541
replay .metricSource .Name , replay .metricSource .Project , expectedDuration .String (),
525
- timeNow .Format (flags .TimeLayout ), r . from .Format (flags .TimeLayout ), startOffsetMinutes , offsetNotice )
542
+ timeNow .Format (flags .TimeLayout ), replay . From .Format (flags .TimeLayout ), startOffsetMinutes , offsetNotice )
526
543
case sdkModels .ReplayConcurrentReplayRunsLimitExhausted :
527
544
return "You've exceeded the limit of concurrent Replay runs. Wait until the current Replay(s) are done."
528
545
case sdkModels .ReplayUnknownAgentVersion :
0 commit comments