in mysql/mysql.go [303:366]
func respectsMinTimeBetweenKills(tx *sql.Tx, now time.Time, term chaosmonkey.Termination, appCfg chaosmonkey.AppConfig, endHour int, loc *time.Location) (err error) {
app := term.Instance.AppName()
account := term.Instance.AccountName()
threshold, err := noKillsSince(appCfg.MinTimeBetweenKillsInWorkDays, now, endHour, loc)
if err != nil {
return err
}
query := "SELECT instance_id, killed_at FROM terminations WHERE app = ? AND account = ? AND killed_at >= ?"
var rows *sql.Rows
args := []interface{}{app, account, threshold.In(time.UTC)}
switch appCfg.Grouping {
case chaosmonkey.App:
// nothing to do
case chaosmonkey.Stack:
query += " AND stack = ?"
args = append(args, term.Instance.StackName())
case chaosmonkey.Cluster:
query += " AND cluster = ?"
args = append(args, term.Instance.ClusterName())
default:
return errors.Errorf("unknown group: %v", appCfg.Grouping)
}
if appCfg.RegionsAreIndependent {
query += " AND region = ?"
args = append(args, term.Instance.RegionName())
}
// For unleashed (real) terminations, we only care about previous
// terminations that were also unleashed. That's because a previous
// leashed termination wasn't a real one, so that wouldn't violate
// the min time between terminations
if !term.Leashed {
query += " AND leashed = FALSE"
}
// We need at most one entry
query += " LIMIT 1"
rows, err = tx.Query(query, args...)
if err != nil {
return err
}
defer func() {
cerr := rows.Close()
if err == nil && cerr != nil {
err = cerr
}
}()
if rows.Next() {
var instanceID string
var killedAt time.Time
err = rows.Scan(&instanceID, &killedAt)
return chaosmonkey.ErrViolatesMinTime{InstanceID: instanceID, KilledAt: killedAt, Loc: loc}
}
return nil
}