func respectsMinTimeBetweenKills()

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
}