feat: check subcommand for firing off expired alarms
This commit is contained in:
parent
9de60f23cc
commit
c6b2148eea
2 changed files with 164 additions and 12 deletions
85
nag
85
nag
|
|
@ -651,20 +651,20 @@ _next_for_rule() {
|
||||||
_time_of_day="$(date -d "@${_timestamp}" +%H:%M:%S)"
|
_time_of_day="$(date -d "@${_timestamp}" +%H:%M:%S)"
|
||||||
|
|
||||||
case "${_rule}" in
|
case "${_rule}" in
|
||||||
hourly) printf "%s" "$((_timestamp + 3600))" ;;
|
hour) printf "%s" "$((_timestamp + 3600))" ;;
|
||||||
daily) date -d "$(date -d "@${_timestamp}" +%Y-%m-%d) + 1 day ${_time_of_day}" +%s ;;
|
day) date -d "$(date -d "@${_timestamp}" +%Y-%m-%d) + 1 day ${_time_of_day}" +%s ;;
|
||||||
weekly) _next_matching_day "${_timestamp}" "${_time_of_day}" "$(date -d "@${_timestamp}" +%u)" ;;
|
week) _next_matching_day "${_timestamp}" "${_time_of_day}" "$(date -d "@${_timestamp}" +%u)" ;;
|
||||||
weekday) _next_matching_day "${_timestamp}" "${_time_of_day}" "1 2 3 4 5" ;;
|
weekday) _next_matching_day "${_timestamp}" "${_time_of_day}" "1 2 3 4 5" ;;
|
||||||
weekend) _next_matching_day "${_timestamp}" "${_time_of_day}" "6 7" ;;
|
weekend) _next_matching_day "${_timestamp}" "${_time_of_day}" "6 7" ;;
|
||||||
mon) _next_matching_day "${_timestamp}" "${_time_of_day}" "1" ;;
|
mon) _next_matching_day "${_timestamp}" "${_time_of_day}" "1" ;;
|
||||||
tue) _next_matching_day "${_timestamp}" "${_time_of_day}" "2" ;;
|
tue) _next_matching_day "${_timestamp}" "${_time_of_day}" "2" ;;
|
||||||
wed) _next_matching_day "${_timestamp}" "${_time_of_day}" "3" ;;
|
wed) _next_matching_day "${_timestamp}" "${_time_of_day}" "3" ;;
|
||||||
thu) _next_matching_day "${_timestamp}" "${_time_of_day}" "4" ;;
|
thu) _next_matching_day "${_timestamp}" "${_time_of_day}" "4" ;;
|
||||||
fri) _next_matching_day "${_timestamp}" "${_time_of_day}" "5" ;;
|
fri) _next_matching_day "${_timestamp}" "${_time_of_day}" "5" ;;
|
||||||
sat) _next_matching_day "${_timestamp}" "${_time_of_day}" "6" ;;
|
sat) _next_matching_day "${_timestamp}" "${_time_of_day}" "6" ;;
|
||||||
sun) _next_matching_day "${_timestamp}" "${_time_of_day}" "7" ;;
|
sun) _next_matching_day "${_timestamp}" "${_time_of_day}" "7" ;;
|
||||||
monthly) _next_month "${_timestamp}" "${_time_of_day}" ;;
|
month) _next_month "${_timestamp}" "${_time_of_day}" ;;
|
||||||
yearly) _next_year "${_timestamp}" "${_time_of_day}" ;;
|
year) _next_year "${_timestamp}" "${_time_of_day}" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1072,6 +1072,67 @@ stop() {
|
||||||
printf "Stopped alarm %s.\\n" "${_target_id}"
|
printf "Stopped alarm %s.\\n" "${_target_id}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check #######################################################################
|
||||||
|
|
||||||
|
describe "check" <<HEREDOC
|
||||||
|
Usage:
|
||||||
|
${_ME} check
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Fire expired alarms. Intended to be run by cron every minute.
|
||||||
|
Repeating alarms are rescheduled. One-shot alarms are removed.
|
||||||
|
HEREDOC
|
||||||
|
check() {
|
||||||
|
[[ -f "${_ALARMS_FILE}" ]] || return 0
|
||||||
|
|
||||||
|
_acquire_lock
|
||||||
|
_read_alarms
|
||||||
|
|
||||||
|
local -a _new_alarms=()
|
||||||
|
local _now
|
||||||
|
_now="$(date +%s)"
|
||||||
|
local _line
|
||||||
|
|
||||||
|
for _line in "${_ALARMS[@]:-}"
|
||||||
|
do
|
||||||
|
[[ -n "${_line}" ]] || continue
|
||||||
|
|
||||||
|
local _id _timestamp _rule _message
|
||||||
|
_id="$(_get_alarm_field "${_line}" 1)"
|
||||||
|
_timestamp="$(_get_alarm_field "${_line}" 2)"
|
||||||
|
_rule="$(_get_alarm_field "${_line}" 3)"
|
||||||
|
_message="$(_get_alarm_field "${_line}" 4)"
|
||||||
|
|
||||||
|
if (( _timestamp <= _now ))
|
||||||
|
then
|
||||||
|
# Fire it.
|
||||||
|
${NAG_CMD} "nag" "${_message}" || _warn printf "Failed to notify: %s\\n" "${_message}"
|
||||||
|
|
||||||
|
if [[ -n "${_rule}" ]]
|
||||||
|
then
|
||||||
|
# Repeating: reschedule.
|
||||||
|
local _next_ts
|
||||||
|
_next_ts="$(_next_occurrence "${_rule}" "${_timestamp}")"
|
||||||
|
_new_alarms+=("$(printf "%s\t%s\t%s\t%s" "${_id}" "${_next_ts}" "${_rule}" "${_message}")")
|
||||||
|
fi
|
||||||
|
# One-shot: drop it (don't add to _new_alarms).
|
||||||
|
else
|
||||||
|
# Not expired — keep it.
|
||||||
|
_new_alarms+=("${_line}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "${#_new_alarms[@]}" -eq 0 ]]
|
||||||
|
then
|
||||||
|
_ALARMS=()
|
||||||
|
: > "${_ALARMS_FILE}"
|
||||||
|
else
|
||||||
|
_ALARMS=("${_new_alarms[@]}")
|
||||||
|
_write_alarms
|
||||||
|
fi
|
||||||
|
_release_lock
|
||||||
|
}
|
||||||
|
|
||||||
# at ##########################################################################
|
# at ##########################################################################
|
||||||
|
|
||||||
describe "at" <<HEREDOC
|
describe "at" <<HEREDOC
|
||||||
|
|
|
||||||
|
|
@ -213,3 +213,94 @@ load test_helper
|
||||||
[[ "${_first_line}" =~ "standup" ]]
|
[[ "${_first_line}" =~ "standup" ]]
|
||||||
[[ "${_second_line}" =~ "take a break" ]]
|
[[ "${_second_line}" =~ "take a break" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check #######################################################################
|
||||||
|
|
||||||
|
# Helper: write a raw alarm line directly to the alarms file.
|
||||||
|
write_alarm() {
|
||||||
|
mkdir -p "${NAG_DIR}"
|
||||||
|
printf "%s\\n" "$1" >> "${NAG_DIR}/alarms"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "check fires expired one-shot and removes it" {
|
||||||
|
local _past_ts=$(( $(date +%s) - 60 ))
|
||||||
|
write_alarm "$(printf "1\t%s\t\tpast alarm" "${_past_ts}")"
|
||||||
|
|
||||||
|
# Record what was fired.
|
||||||
|
local _fired="${NAG_DIR}/fired"
|
||||||
|
export NAG_CMD="${NAG_DIR}/recorder"
|
||||||
|
cat > "${NAG_CMD}" <<'SCRIPT'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
printf "%s\n" "$2" >> "${NAG_DIR}/fired"
|
||||||
|
SCRIPT
|
||||||
|
chmod +x "${NAG_CMD}"
|
||||||
|
|
||||||
|
run "${_NAG}" check
|
||||||
|
[ "${status}" -eq 0 ]
|
||||||
|
|
||||||
|
# Alarm should have been removed.
|
||||||
|
[[ ! -s "${NAG_DIR}/alarms" ]] || [ "$(wc -l < "${NAG_DIR}/alarms")" -eq 0 ]
|
||||||
|
|
||||||
|
# Notification should have fired.
|
||||||
|
grep -q "past alarm" "${_fired}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "check reschedules expired repeating alarm" {
|
||||||
|
local _past_ts=$(( $(date +%s) - 60 ))
|
||||||
|
write_alarm "$(printf "1\t%s\tday\tdaily alarm" "${_past_ts}")"
|
||||||
|
|
||||||
|
run "${_NAG}" check
|
||||||
|
[ "${status}" -eq 0 ]
|
||||||
|
|
||||||
|
# Alarm should still exist with a future timestamp.
|
||||||
|
[ -s "${NAG_DIR}/alarms" ]
|
||||||
|
local _new_ts
|
||||||
|
_new_ts="$(cut -f2 "${NAG_DIR}/alarms" | head -1)"
|
||||||
|
local _now
|
||||||
|
_now="$(date +%s)"
|
||||||
|
(( _new_ts > _now ))
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "check does not fire future alarms" {
|
||||||
|
local _future_ts=$(( $(date +%s) + 3600 ))
|
||||||
|
write_alarm "$(printf "1\t%s\t\tfuture alarm" "${_future_ts}")"
|
||||||
|
|
||||||
|
run "${_NAG}" check
|
||||||
|
[ "${status}" -eq 0 ]
|
||||||
|
|
||||||
|
# Alarm should still be there, unchanged.
|
||||||
|
[ -s "${NAG_DIR}/alarms" ]
|
||||||
|
grep -q "future alarm" "${NAG_DIR}/alarms"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "check fires all missed alarms" {
|
||||||
|
local _past1=$(( $(date +%s) - 120 ))
|
||||||
|
local _past2=$(( $(date +%s) - 60 ))
|
||||||
|
write_alarm "$(printf "1\t%s\t\tmissed one" "${_past1}")"
|
||||||
|
write_alarm "$(printf "2\t%s\t\tmissed two" "${_past2}")"
|
||||||
|
|
||||||
|
local _fired="${NAG_DIR}/fired"
|
||||||
|
export NAG_CMD="${NAG_DIR}/recorder"
|
||||||
|
cat > "${NAG_CMD}" <<'SCRIPT'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
printf "%s\n" "$2" >> "${NAG_DIR}/fired"
|
||||||
|
SCRIPT
|
||||||
|
chmod +x "${NAG_CMD}"
|
||||||
|
|
||||||
|
run "${_NAG}" check
|
||||||
|
[ "${status}" -eq 0 ]
|
||||||
|
|
||||||
|
# Both should have fired.
|
||||||
|
grep -q "missed one" "${_fired}"
|
||||||
|
grep -q "missed two" "${_fired}"
|
||||||
|
|
||||||
|
# Both should be removed (one-shots).
|
||||||
|
[[ ! -s "${NAG_DIR}/alarms" ]] || [ "$(wc -l < "${NAG_DIR}/alarms")" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "help check shows check usage" {
|
||||||
|
run "${_NAG}" help check
|
||||||
|
[ "${status}" -eq 0 ]
|
||||||
|
[[ "${output}" =~ "Usage:" ]]
|
||||||
|
[[ "${output}" =~ "check" ]]
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue