From 704720c4cd5d7ee3a72f003f246cf6815d4a533b Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Mon, 2 Sep 2024 22:42:53 +0200 Subject: [PATCH] fix: [cron] use env as cache key to avoid improper cache hit between multiple services on same charm --- cron/lib/common | 43 ++++++++++++++++++++++++---------- cron/test/entries_from_service | 15 ++++++++++++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/cron/lib/common b/cron/lib/common index 66feeb7..43e0c0c 100644 --- a/cron/lib/common +++ b/cron/lib/common @@ -1,11 +1,12 @@ # -*- mode: shell-script -*- cron:get_config() { - local cfg="$1" + local cfg="$1" env_hash="$2" local cache_file="$CACHEDIR/$FUNCNAME.cache.$(H "$@")" \ type value + local k v E E1 title command lock_opts schedule if [ -e "$cache_file" ]; then - #debug "$FUNCNAME: SESSION cache hit $1" + debug "$FUNCNAME: SESSION cache hit $1" cat "$cache_file" return 0 fi @@ -13,7 +14,7 @@ cron:get_config() { case "$type" in "sequence") while read-0-err E s; do - cron:get_config "$s" || return 1 + cron:get_config "$s" "$env_hash" || return 1 done < <(e "$cfg" | p-err shyaml -q get-values-0 -y) if [ "$E" != 0 ]; then err "Failed to parse sequence while reading config." @@ -30,7 +31,7 @@ cron:get_config() { return 1 fi p0 "$schedule" "$lock_opts" "$k" "$command" - done < <(p-err cron:get_config "$v") + done < <(p-err cron:get_config "$v" "$env_hash") if [ "$E1" != 0 ]; then err "Failed to parse value of key '$k' in struct config." return 1 @@ -69,7 +70,7 @@ cron:get_config() { err "Unrecognized type '$type'." return 1 fi - cron:get_config "$value" || return 1 + cron:get_config "$value" "$env_hash" || return 1 ;; esac > "$cache_file.tmp" @@ -89,12 +90,13 @@ cron:get_config() { } + cron:entries_from_service() { local service="$1" relation_cfg="$2" \ cache_file="$CACHEDIR/$FUNCNAME.cache.$(H "$@")" \ - label schedule lock_opts title command full_label + label schedule lock_opts title command full_label H if [ -e "$cache_file" ]; then - #debug "$FUNCNAME: SESSION cache hit $1" + debug "$FUNCNAME: SESSION cache hit $1" cat "$cache_file" return 0 fi @@ -107,6 +109,16 @@ cron:entries_from_service() { BASE_CHARM_PATH=$(charm.get_dir "$BASE_CHARM_NAME") || return 1 export MASTER_BASE_{CHARM,SERVICE}_NAME BASE_CHARM_{PATH,NAME} + + H=$( + env_vars=(MASTER_BASE_{CHARM,SERVICE}_NAME BASE_CHARM_{PATH,NAME} BASE_SERVICE_NAME) + values=() + for v in "${env_vars[@]}"; do + values+=("${!v}") + done + H "${values[@]}" + ) + label="launch-$service" while read-0-err E schedule lock_opts title command; do lock_opts=($lock_opts) @@ -136,7 +148,8 @@ cron:entries_from_service() { p0 "$schedule lock ${full_label} ${lock_opts[*]} -c \"$command\" 2>&1 | awk '{ print strftime(\"%Y-%m-%d %H:%M:%S %Z\"), \$0; fflush(); }' >> /var/log/cron/${full_label}_script.log" - done < <(p-err cron:get_config "$relation_cfg") > "$cache_file" + done < <(p-err cron:get_config "$relation_cfg" "$H") > "$cache_file.tmp" + mv "$cache_file.tmp" "$cache_file" >&2 if [ "$E" != 0 ]; then rm -f "$cache_file" err "Failed to get ${DARKYELLOW}$service${NORMAL}--${DARKBLUE}schedule-command${NORMAL}-->${DARKYELLOW}$SERVICE_NAME${NORMAL}'s config." @@ -149,7 +162,7 @@ cron:entries_from_service() { cron:lock_opts() { local cache_file="$CACHEDIR/$FUNCNAME.cache.$(H "$@")" \ - label schedule lock_opts title command full_label + label schedule lock_opts title if [ -e "$cache_file" ]; then #debug "$FUNCNAME: SESSION cache hit $1" cat "$cache_file" @@ -198,13 +211,17 @@ cron:entries() { if [ -z "$ALL_RELATIONS" ]; then err "Expected \$ALL_RELATIONS to be set." - exit 1 + return 1 fi - export TARGET_SERVICE_NAME=$SERVICE_NAME + export TARGET_SERVICE_NAME="$SERVICE_NAME" while read-0 service relation_cfg; do - debug "service: '$service' relation_cfg: '$relation_cfg'" + debug "service: '$service' relation_cfg:" >&2 + e "$relation_cfg" | prefix " | " >&2 + echo "" >&2 + cron:entries_from_service "$service" "$relation_cfg" || return 1 - done < <(get_service_incoming_relations "$SERVICE_NAME" "schedule-command") > "$cache_file" + done < <(get_service_incoming_relations "$SERVICE_NAME" "schedule-command") > "$cache_file.tmp" + mv "$cache_file.tmp" "$cache_file" >&2 cat "$cache_file" } export -f cron:entries \ No newline at end of file diff --git a/cron/test/entries_from_service b/cron/test/entries_from_service index 739b5db..b540338 100644 --- a/cron/test/entries_from_service +++ b/cron/test/entries_from_service @@ -154,3 +154,18 @@ noerror is out "\ 0 0 * * * lock launch-foo -p 10 -k -c \"dc run --rm foo foo\" 2>&1 | awk '{ print strftime(\"%Y-%m-%d %H:%M:%S %Z\"), \$0; fflush(); }' >> /var/log/cron/launch-foo_script.log" TRIM + +try " +set -o pipefail && +cfg='!var-expand +(0 0 * * *) {-p 10 -k} dc run --rm \$BASE_SERVICE_NAME \$MASTER_BASE_SERVICE_NAME +' +cron:entries_from_service 'foo1' \"\$cfg\" | tr '\0' '\n' +cron:entries_from_service 'foo2' \"\$cfg\" | tr '\0' '\n' +" "using relation's var, same conf, different env" +noerror +is out "\ +0 0 * * * lock launch-foo1 -p 10 -k -c \"dc run --rm foo1 foo1\" 2>&1 | awk '{ print strftime(\"%Y-%m-%d %H:%M:%S %Z\"), \$0; fflush(); }' >> /var/log/cron/launch-foo1_script.log +0 0 * * * lock launch-foo2 -p 10 -k -c \"dc run --rm foo2 foo2\" 2>&1 | awk '{ print strftime(\"%Y-%m-%d %H:%M:%S %Z\"), \$0; fflush(); }' >> /var/log/cron/launch-foo2_script.log\ +" TRIM +