Implement a state manager POC
This commit is contained in:
parent
6a855e1d60
commit
e42a2b248f
1 changed files with 149 additions and 48 deletions
193
rowbot
193
rowbot
|
@ -97,23 +97,6 @@ b64_encode() {
|
||||||
|
|
||||||
# code reloading helpers
|
# code reloading helpers
|
||||||
|
|
||||||
get_option() {
|
|
||||||
local var_name=${1//-/_}
|
|
||||||
local env_var=${var_name^^}
|
|
||||||
|
|
||||||
if [[ ! -v config[$1] || -v OPT_OW ]]; then
|
|
||||||
if [[ -v $env_var ]]; then
|
|
||||||
config[$1]=${!env_var}
|
|
||||||
elif [[ -v opts[$1] ]]; then
|
|
||||||
config[$1]=${opts[$1]}
|
|
||||||
elif [[ -v $var_name ]]; then
|
|
||||||
config[$1]=${!var_name}
|
|
||||||
elif (( $# > 1 )); then
|
|
||||||
config[$1]=$2
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
is_reloaded() {
|
is_reloaded() {
|
||||||
[[ $RELOADED = yes ]] || (( RELOAD_COUNT ))
|
[[ $RELOADED = yes ]] || (( RELOAD_COUNT ))
|
||||||
}
|
}
|
||||||
|
@ -157,11 +140,7 @@ shuffle() {
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# misc
|
# process management and friends
|
||||||
|
|
||||||
is_running () {
|
|
||||||
kill -0 "$1" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
die() {
|
die() {
|
||||||
local fmt=$1
|
local fmt=$1
|
||||||
|
@ -181,6 +160,12 @@ has() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_running () {
|
||||||
|
kill -0 "$1" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# misc
|
||||||
|
|
||||||
run_callbacks() {
|
run_callbacks() {
|
||||||
if (( ! $# )); then
|
if (( ! $# )); then
|
||||||
return 1
|
return 1
|
||||||
|
@ -245,12 +230,12 @@ url() {
|
||||||
}
|
}
|
||||||
|
|
||||||
###
|
###
|
||||||
# configure rowbot's environment
|
# Prepare rowbot's configuration
|
||||||
###
|
###
|
||||||
|
|
||||||
# parse command line arguments
|
# parse command line arguments
|
||||||
|
|
||||||
declare -A opts
|
declare -A config opts
|
||||||
cmd_line=( "${@:0}" )
|
cmd_line=( "${@:0}" )
|
||||||
|
|
||||||
while (( $# )); do
|
while (( $# )); do
|
||||||
|
@ -280,6 +265,8 @@ done
|
||||||
|
|
||||||
# load custom configuration files
|
# load custom configuration files
|
||||||
|
|
||||||
|
mapfile -t old_set < <(compgen -v)
|
||||||
|
|
||||||
for file do
|
for file do
|
||||||
if [[ -f $file ]]; then
|
if [[ -f $file ]]; then
|
||||||
# These files (if any) are provided dynamically at run-time.
|
# These files (if any) are provided dynamically at run-time.
|
||||||
|
@ -290,27 +277,131 @@ for file do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
mapfile -t new_set < <(compgen -v)
|
||||||
|
|
||||||
|
for new in "${new_set[@]}"; do
|
||||||
|
found=0
|
||||||
|
|
||||||
|
for old in "${old_set[@]}"; do
|
||||||
|
if [[ $new = "$old" ]]; then
|
||||||
|
found=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if (( !found )); then
|
||||||
|
config[$new]=${!new}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for setting in "${!opts[@]}"; do
|
||||||
|
config[$setting]=${opts[$setting]}
|
||||||
|
done
|
||||||
|
|
||||||
|
while IFS= read -r setting; do
|
||||||
|
config[${setting,,}]=${!setting}
|
||||||
|
done < <(compgen -e)
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
|
|
||||||
unset key file
|
unset key opts old_set file new_set new found old setting
|
||||||
|
|
||||||
###
|
###
|
||||||
# load default config
|
# state management
|
||||||
###
|
###
|
||||||
|
|
||||||
declare -A config
|
state_resolve() {
|
||||||
|
local ns=${NS-global} managed found=0
|
||||||
|
declare -gA __rowbot_state_store_"$ns"
|
||||||
|
declare -n ns_config=__rowbot_state_store_"$ns"
|
||||||
|
|
||||||
get_option owner "${USER:-uplime}"
|
if [[ $ns != global ]]; then
|
||||||
get_option trigger \`
|
for managed in "${states_managed[@]}"; do
|
||||||
get_option dev yes
|
if [[ $managed = "$ns" ]]; then
|
||||||
|
found=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if (( !found )); then
|
||||||
|
states_managed+=( "$ns" )
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -v config[$1] ]]; then
|
||||||
|
ns_config[$1]=${config[$1]}
|
||||||
|
elif [[ -v DEFAULT ]]; then
|
||||||
|
ns_config[$1]=$DEFAULT
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
state_get() {
|
||||||
|
local ns=${NS-global}
|
||||||
|
# The `ns_config` variable is a reference to an array
|
||||||
|
# shellcheck disable=SC2178
|
||||||
|
declare -n ns_config=__rowbot_state_store_"$ns"
|
||||||
|
|
||||||
|
if [[ -v ns_config[$1] ]]; then
|
||||||
|
printf %s "${ns_config[$1]}"
|
||||||
|
elif [[ -v DEFAULT ]]; then
|
||||||
|
printf %s "$DEFAULT"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
state_has() {
|
||||||
|
local ns=${NS-global} found=1 managed
|
||||||
|
declare -n ns_config=__rowbot_state_store_"$ns"
|
||||||
|
|
||||||
|
for managed in "${ns_config[@]}"; do
|
||||||
|
if [[ $managed = "$1" ]]; then
|
||||||
|
found=0
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return "$found"
|
||||||
|
}
|
||||||
|
|
||||||
|
on_sys_init_001_state() {
|
||||||
|
states_managed=( global )
|
||||||
|
}
|
||||||
|
|
||||||
|
on_sys_before_999_state() {
|
||||||
|
local managed
|
||||||
|
|
||||||
|
for managed in "${states_managed[@]}"; do
|
||||||
|
put_assoc_array __rowbot_state_store_"$managed"
|
||||||
|
done
|
||||||
|
|
||||||
|
put_array states_managed
|
||||||
|
}
|
||||||
|
|
||||||
|
on_sys_after_001_state() {
|
||||||
|
local managed
|
||||||
|
get_array states_managed
|
||||||
|
|
||||||
|
for managed in "${states_managed[@]}"; do
|
||||||
|
get_assoc_array __rowbot_state_store_"$managed"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
###
|
###
|
||||||
# logger
|
# logger
|
||||||
###
|
###
|
||||||
|
|
||||||
log() {
|
log() {
|
||||||
if [[ -v LOG_LEVEL ]] && (( log_levels[$log_level] <= log_levels[$LOG_LEVEL] )); then
|
if NS=log state_has fd; then
|
||||||
printf "%s: $1\n" "${LOG_LEVEL^^}" "${@:2}" >&"$log_fd"
|
# The only possible fail conditions are already checked for.
|
||||||
|
# shellcheck disable=SC2155
|
||||||
|
local level=$(NS=log state_get level) fd=$(NS=log state_get fd)
|
||||||
|
|
||||||
|
if (( log_levels[$level] <= log_levels[$LOG_LEVEL] )); then
|
||||||
|
printf "%s: $1\n" "${LOG_LEVEL^^}" "${@:2}" >&"$fd"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,40 +437,50 @@ log_has_level() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
on_sys_init_001_log() {
|
on_sys_init_005_log() {
|
||||||
declare -gA log_levels=( [trace]=1 [debug]=2 [info]=3 [warn]=4 [error]=5 )
|
declare -gA log_levels=( [trace]=1 [debug]=2 [info]=3 [warn]=4 [error]=5 )
|
||||||
get_option log-level info
|
NS=log DEFAULT=info state_resolve level
|
||||||
|
|
||||||
if ! log_has_level "${config[log-level]}"; then
|
if ! log_has_level "$(NS=log state_get level)"; then
|
||||||
die "%s is not a valid logging level" "${config[log-level]}"
|
die "%s is not a valid logging level" "$(NS=log state_get level)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
get_option log ""
|
local log_fd=1
|
||||||
get_option overwrite no
|
|
||||||
log_level=${config[log-level]}
|
|
||||||
|
|
||||||
if [[ ${config[log]} ]]; then
|
if [[ -v ${config[log]} ]]; then
|
||||||
if [[ ${config[overwrite]} = yes ]]; then
|
if [[ ${config[overwrite]} = yes ]]; then
|
||||||
exec {log_fd}>"${config[log]}"
|
exec {log_fd}>"${config[log]}"
|
||||||
else
|
else
|
||||||
exec {log_fd}>>"${config[log]}"
|
exec {log_fd}>>"${config[log]}"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
log_fd=1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
NS=log DEFAULT=$log_fd state_resolve fd
|
||||||
}
|
}
|
||||||
|
|
||||||
on_sys_before_999_log() {
|
on_sys_before_999_log() {
|
||||||
if [[ -v log_fd ]] && (( log_fd != 1 )); then
|
if NS=log state_has fd; then
|
||||||
|
# The only possible fail condition is already checked for.
|
||||||
|
# shellcheck disable=2155
|
||||||
|
local fd=$(NS=log state_get fd)
|
||||||
|
|
||||||
|
if (( fd != 1 )); then
|
||||||
log_debug "shutting logger down for reload"
|
log_debug "shutting logger down for reload"
|
||||||
exec {log_fd}>&-
|
exec {fd}>&-
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
on_sys_exit_999_log() {
|
on_sys_exit_999_log() {
|
||||||
if [[ -v log_fd ]] && (( log_fd != 1 )); then
|
if NS=log state_has fd; then
|
||||||
|
# The only possible fail condition is already checked for.
|
||||||
|
# shellcheck disable=2155
|
||||||
|
local fd=$(NS=log state_get fd)
|
||||||
|
|
||||||
|
if (( fd != 1 )); then
|
||||||
log_debug "shutting logger down for good"
|
log_debug "shutting logger down for good"
|
||||||
exec {log_fd}>&-
|
exec {fd}>&-
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue