Files
spring-async-demo/scheduling/scripts/three-replicas.sh
Ankur Mhatre 6af6e4a3f1 Add the scheduling module
Three replicas of one application against one PostgreSQL database, proving
duplicate @Scheduled execution and then removing it with ShedLock: 24
executions where 8 were due, then 7 for 7 ticks.

Also measured: @SchedulerLock without @EnableSchedulerLock does nothing and
warns about nothing; spring.task.scheduling.pool.size=1 does not starve a
fixedRate job but delays it and fires 35 of 40 executions in a burst; and a
node whose clock is 40 seconds fast takes a live lock unless the provider
uses usingDbTime().
2026-09-01 23:28:06 +05:30

53 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Starts three replicas of the application against one database, lets the schedule tick, and
# tallies who ran the job.
#
# scripts/three-replicas.sh unlocked # no @EnableSchedulerLock: every replica runs it
# scripts/three-replicas.sh locked # ShedLock with usingDbTime()
# scripts/three-replicas.sh appclock 40 # ShedLock without usingDbTime(), replica-3 40s fast
#
# Environment:
# RUN_FOR seconds to let the schedule tick (default 30; three JVMs need ~10s to start)
# JOB_DURATION ISO-8601 duration the job sleeps for (default PT0.2S)
set -euo pipefail
cd "$(dirname "$0")/.."
PROFILE="${1:-unlocked}"
SKEW_SECONDS="${2:-0}"
RUN_FOR="${RUN_FOR:-30}"
JOB_DURATION="${JOB_DURATION:-PT0.2S}"
JAR=target/scheduling-1.0.jar
PSQL=(scripts/postgres.sh psql)
[ -f "$JAR" ] || mvn -B -q -DskipTests package
"${PSQL[@]}" -q -c "delete from job_execution" -c "delete from shedlock" >/dev/null 2>&1 || true
pids=()
for n in 1 2 3; do
skew=()
if [ "$SKEW_SECONDS" != "0" ] && [ "$n" = "3" ]; then
skew=(-Dclock.skew="PT${SKEW_SECONDS}S")
fi
java -Dspring.profiles.active="$PROFILE" -DINSTANCE_ID="replica-$n" \
-Djob.duration="$JOB_DURATION" "${skew[@]}" \
-jar "$JAR" > "target/replica-$n.log" 2>&1 &
pids+=($!)
done
sleep "$RUN_FOR"
for p in "${pids[@]}"; do kill "$p" 2>/dev/null || true; done
wait 2>/dev/null || true
echo "profile=$PROFILE replicas=3 run-for=${RUN_FOR}s job rate=3s job duration=$JOB_DURATION replica-3 clock skew=${SKEW_SECONDS}s"
echo
echo "-- every execution, in order --"
"${PSQL[@]}" -c "select instance_id, to_char(started_at,'HH24:MI:SS.MS') as started_at from job_execution order by started_at"
echo "-- executions per replica --"
"${PSQL[@]}" -c "select instance_id, count(*) from job_execution group by instance_id order by instance_id"
OVERLAP="b.id > a.id and b.instance_id <> a.instance_id and b.started_at < a.started_at + interval '$JOB_DURATION'"
echo "-- pairs of executions that overlapped (a second replica started while the first was still working) --"
"${PSQL[@]}" -c "select count(*) as overlapping_pairs from job_execution a join job_execution b on $OVERLAP"
"${PSQL[@]}" -c "select a.instance_id as first, to_char(a.started_at, 'HH24:MI:SS.MS') as first_at, b.instance_id as second, to_char(b.started_at, 'HH24:MI:SS.MS') as second_at from job_execution a join job_execution b on $OVERLAP order by a.started_at limit 6"
echo "-- the lock row --"
"${PSQL[@]}" -c "select name, locked_by, to_char(locked_at,'HH24:MI:SS.MS') as locked_at, to_char(lock_until,'HH24:MI:SS.MS') as lock_until from shedlock"