Add batch-llm module: 100,000 synthetic tickets classified by a ChatClient in a Spring Batch 6 chunk step with Resilience4j rate limiting and retry, skip-and-record for malformed JSON, restart after kill -9 in a second JVM, and a per-chunk cost ledger. The model is a deterministic simulated ChatModel; prices are configurable placeholders. No provider called.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017ic4b4VQVEJWetTT1dYzyJ
This commit is contained in:
2026-10-29 06:10:22 +00:00
co-authored by Claude Sonnet 5.5
parent aa8b1604ed
commit 6d792f00e0
48 changed files with 2093 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
# sourced by the other scripts
export JAVA_HOME="${JDK25:-/tmp/tools/jdk-25.0.5+8}" # Java 25 required
export PATH="$JAVA_HOME/bin:/opt/maven/bin:$PATH"
cd "$(dirname "${BASH_SOURCE[0]}")/.."
JAR=target/batch-llm-1.0.0.jar
TICKETS="${TICKETS:-100000}"
CHUNK=100
clean_log() { grep -v "^Picked up JAVA_TOOL_OPTIONS" ; }
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Same tickets, same fault plan: the crashed-and-resumed database must hold exactly the clean run's results.
set -euo pipefail
source "$(dirname "$0")/common.sh"
{ echo "# Clean run vs crashed-and-resumed run"; echo
for f in target/clean/run.log target/crash/jvm2.log; do
echo "## $f"
grep -E "^tickets total|^ledger|results checksum|billed calls the ledger" "$f"
echo
done; } > output/10-compare.txt
cat output/10-compare.txt
a=$(grep checksum target/clean/run.log | awk '{print $NF}'); b=$(grep checksum target/crash/jvm2.log | awk '{print $NF}')
[ "$a" = "$b" ] && echo "checksums identical: $a" | tee -a output/10-compare.txt || { echo "CHECKSUMS DIFFER $a $b" | tee -a output/10-compare.txt; exit 1; }
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Two real JVMs. JVM 1 is killed with SIGKILL once it has committed KILL_AT chunks; JVM 2 starts the
# same job (same run.id, same H2 file) and finishes it. Nothing is shut down gracefully.
set -euo pipefail
source "$(dirname "$0")/common.sh"
[ -f "$JAR" ] || mvn -B -q -T1 package -DskipTests
CHUNKS=$((TICKETS / CHUNK))
KILL_AT=$(( (CHUNKS * 4 / 10 / 50) * 50 )); [ "$KILL_AT" -ge 50 ] || KILL_AT=50
D=target/crash
rm -rf $D && mkdir -p $D output
OPTS=(--batch.llm.tickets="$TICKETS" --batch.llm.run-id=crash-demo
--spring.datasource.url="jdbc:h2:file:./$D/batchdb;DB_CLOSE_ON_EXIT=FALSE"
--sim.provider.meter-file=$D/provider-meter.bin)
java -jar "$JAR" "${OPTS[@]}" > $D/jvm1.log 2>&1 &
PID=$!
echo "JVM 1 started, pid $PID; waiting for $KILL_AT committed chunks"
while kill -0 "$PID" 2>/dev/null; do
if grep -q "committed-chunks-this-jvm=$KILL_AT " $D/jvm1.log; then
kill -9 "$PID"; echo "kill -9 sent to JVM 1 (pid $PID)"; break
fi
sleep 0.2
done
wait "$PID" 2>/dev/null || true
echo "JVM 1 exit code: $? (137 = SIGKILL)"
echo "--- last lines JVM 1 printed:"; clean_log < $D/jvm1.log | tail -3
echo "--- JVM 2 (same run.id, same database file):"
java -jar "$JAR" "${OPTS[@]}" 2>&1 | clean_log | grep -v '^PROGRESS' | tee $D/jvm2.log
{ echo "# Crash and restart, $TICKETS tickets: JVM 1 killed with kill -9 after $KILL_AT committed chunks, JVM 2 resumes"; echo;
echo "## JVM 1 (progress lines, then SIGKILL)"; clean_log < $D/jvm1.log | tail -4; echo "(process killed by SIGKILL; no shutdown hook ran)"; echo;
echo "## JVM 2"; cat $D/jvm2.log; } > output/09-crash-restart.txt
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Regenerates every file under output/. No API key, no Docker, no network beyond Maven Central.
# Takes several minutes on a busy 2-vCPU machine: the 100,000-ticket job runs twice (once clean,
# once crashed and resumed). TICKETS=20000 scripts/run-all.sh gives a quicker, smaller version.
set -euo pipefail
source "$(dirname "$0")/common.sh"
rm -rf output target/test-db target/test-meters
mvn -B -q -T1 package 2>&1 | grep -E "Tests run:|BUILD|FAIL|ERROR" || true
scripts/run-clean.sh
scripts/crash-restart.sh
scripts/compare.sh
ls output
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# One uninterrupted run of the whole job against a fresh database and a fresh provider meter.
set -euo pipefail
source "$(dirname "$0")/common.sh"
[ -f "$JAR" ] || mvn -B -q -T1 package -DskipTests
rm -rf target/clean && mkdir -p target/clean output
java -jar "$JAR" --batch.llm.tickets="$TICKETS" --batch.llm.run-id=clean \
--spring.datasource.url="jdbc:h2:file:./target/clean/batchdb;DB_CLOSE_ON_EXIT=FALSE" \
--sim.provider.meter-file=target/clean/provider-meter.bin 2>&1 | clean_log | tee target/clean/run.log
{ echo "# One uninterrupted run, $TICKETS tickets (java -jar, fresh H2 file, fresh provider meter)"; echo;
grep -v '^PROGRESS' target/clean/run.log; } > output/08-clean-run.txt