#!/bin/bash # Make sure the state directory exists and create it if not ensure_state_dir() { local state_dir="${STATE_DIR:?}" if ! [ -d "$(dirname "$state_dir")" ]; then errlog "ERROR: Parent directory of STATE_DIR '$state_dir' doesn't exist." return 1 elif ! [ -d "$state_dir" ]; then if ! mkdir "$state_dir"; then errlog "ERROR: Failed to create STATE_DIR '$state_dir'." return 2 fi fi } # Get the configured TTL for a state key get_state_ttl() { local state_file="${1:?Missing state file}" local ttl_file="$state_file.ttl" local state_ttl state_ttl="$(cat "$ttl_file" 2>/dev/null)" if ! is_int "$state_ttl"; then errlog "WARN: Invalid value '$state_ttl' in '$ttl_file'. Assuming value 0." state_ttl=0 fi echo "$state_ttl" } # Get the age of a state key get_state_age() { local state_file="${1:?Missing state file}" local state_mod state_mod="$(stat -c%Y "$state_file")" echo "$(($(current_ue) - state_mod))" } # Check if a state has expired state_is_expired() { local state_file="${1:?Missing state file}" local state_ttl state_mod state_ttl="$(get_state_ttl "$state_file")" [ "$state_ttl" -eq 0 ] && return 1 [ "$(get_state_age "$state_file")" -gt "$state_ttl" ] && return 0 } # Remove a state rm_state() { local key="${1:?Missing key}" local state_file="$STATE_DIR/$key" local ttl_file="$state_file.ttl" rm "$state_file" "$ttl_file" } # Check if a state key name is valid state_key_is_valid() { local key="${1:?Missing key}" regex="^([0-9]|[a-z]|[A-Z]|-)*$" if ! [[ "$key" =~ $regex ]]; then errlog "ERROR: Key '$key' doesn't match regex '$regex'." return 1 fi } # Write a value to a state key and optionally set a TTL set_state() { local key="${1:?Missing key}" value="$2" ttl="${3:-0}" local state_file="$STATE_DIR/$key" local ttl_file="$state_file.ttl" state_key_is_valid "$key" || return 1 ensure_state_dir || return 2 echo "$value" >"$state_file" echo "$ttl" >"$ttl_file" } # Read a value from a state key get_state() { local key="${1:?Missing key}" local state_file="$STATE_DIR/$key" state_key_is_valid "$key" || return 1 ensure_state_dir || return 2 if ! [ -f "$state_file" ]; then errlog "WARN: State file doesn't exist: '$state_file'" return 3 elif state_is_expired "$state_file"; then errlog "WARN: State file has expired: '$state_file'" rm_state "$key" return 4 fi cat "$state_file" }