test(workflow): verify-domain fires the 14-day timer and asserts escalation (S-14, refs #15)
Extend the live verify-domain check: a third registration parks at Beoordelen, its boundary timer is fired early via Flowable's management API, and the check polls until the domain escalation worker reassigns the still-open task's candidate group from behandelaar to teamlead (ADR-0015). Runs on the CI verify-stack. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -157,4 +157,80 @@ for _ in $(seq 1 15); do
|
|||||||
done
|
done
|
||||||
[ -n "$gone" ] || { echo "FAIL — Beoordelen task for $reg_id2 still active after withdrawal" >&2; docker logs "$dom" 2>&1 | tail -15 >&2; exit 1; }
|
[ -n "$gone" ] || { echo "FAIL — Beoordelen task for $reg_id2 still active after withdrawal" >&2; docker logs "$dom" 2>&1 | tail -15 >&2; exit 1; }
|
||||||
echo "OK — withdrawal cancelled the Beoordelen task; the registratie process ended (ingetrokken)"
|
echo "OK — withdrawal cancelled the Beoordelen task; the registratie process ended (ingetrokken)"
|
||||||
|
|
||||||
|
# ── S-14: escalation. A third registration parks at Beoordelen. We fire its 14-day boundary timer
|
||||||
|
# early via Flowable's management API (the timer job is moved to executable and run), which routes a
|
||||||
|
# parallel token to the BeoordelingEscaleren external task. The domain's escalation worker acquires
|
||||||
|
# it and reassigns the still-open Beoordelen task from the behandelaar group to teamlead (ADR-0015). ─
|
||||||
|
echo ">> submitting a third registration to escalate"
|
||||||
|
loc3="$(docker run --rm --network "$net" curlimages/curl:latest \
|
||||||
|
-fsS -D - -o /dev/null -X POST "http://$dom_ip:8080/registrations" \
|
||||||
|
-H 'Content-Type: application/json' -d '{"bsn":"123456782"}' \
|
||||||
|
| sed -n 's/\r$//; s/^[Ll]ocation: //p' | head -1)"
|
||||||
|
[ -n "$loc3" ] || { echo "FAIL — third POST /registrations returned no Location" >&2; exit 1; }
|
||||||
|
reg_id3="${loc3##*/}"
|
||||||
|
echo ">> third registration $reg_id3"
|
||||||
|
|
||||||
|
# Extracts "<taskId> <processInstanceId>" for a registration from a task-query response on stdin.
|
||||||
|
task_and_pid_for_reg() { REG_ID="$1" python3 -c "import os,sys,json
|
||||||
|
try:
|
||||||
|
d=json.load(sys.stdin)
|
||||||
|
except Exception:
|
||||||
|
d={}
|
||||||
|
rid=os.environ['REG_ID']
|
||||||
|
t=next((t for t in (d.get('data') or [])
|
||||||
|
if any(v.get('name')=='registrationId' and v.get('value')==rid for v in (t.get('variables') or []))), None)
|
||||||
|
print(f\"{t['id']} {t['processInstanceId']}\" if t else '')"; }
|
||||||
|
|
||||||
|
# The candidate groups on a task (space-separated, sorted) from a runtime identitylinks response.
|
||||||
|
candidate_groups() { python3 -c "import sys,json
|
||||||
|
try:
|
||||||
|
links=json.load(sys.stdin)
|
||||||
|
except Exception:
|
||||||
|
links=[]
|
||||||
|
print(' '.join(sorted(l.get('group') or '' for l in links if l.get('type')=='candidate' and l.get('group'))))"; }
|
||||||
|
|
||||||
|
# The first job id in a management jobs/timer-jobs response on stdin.
|
||||||
|
first_job_id() { python3 -c "import sys,json
|
||||||
|
try:
|
||||||
|
d=json.load(sys.stdin)
|
||||||
|
except Exception:
|
||||||
|
d={}
|
||||||
|
print(((d.get('data') or [{}])[0]).get('id',''))"; }
|
||||||
|
|
||||||
|
echo ">> polling Flowable for its Beoordelen task"
|
||||||
|
task_id3=""; pid3=""
|
||||||
|
for _ in $(seq 1 30); do
|
||||||
|
resp="$(flcurl -X POST "$fl_base/query/tasks" -H 'Content-Type: application/json' -d "$query" 2>/dev/null || true)"
|
||||||
|
read -r task_id3 pid3 <<<"$(printf '%s' "$resp" | task_and_pid_for_reg "$reg_id3")"
|
||||||
|
[ -n "$task_id3" ] && break
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
[ -n "$task_id3" ] || { echo "FAIL — no Beoordelen task appeared for registration $reg_id3" >&2; docker logs "$dom" 2>&1 | tail -15 >&2; exit 1; }
|
||||||
|
echo ">> Beoordelen task $task_id3 (instance $pid3) is waiting for the behandelaar"
|
||||||
|
|
||||||
|
echo ">> asserting the task starts out claimable by the behandelaar group"
|
||||||
|
before="$(flcurl "$fl_base/runtime/tasks/$task_id3/identitylinks" | candidate_groups)"
|
||||||
|
[ "$before" = "behandelaar" ] || { echo "FAIL — expected candidate group 'behandelaar', got '$before'" >&2; exit 1; }
|
||||||
|
|
||||||
|
echo ">> firing the 14-day boundary timer early via the management API"
|
||||||
|
timer_id="$(flcurl "$fl_base/management/timer-jobs?processInstanceId=$pid3" | first_job_id)"
|
||||||
|
[ -n "$timer_id" ] || { echo "FAIL — no timer job found for instance $pid3" >&2; exit 1; }
|
||||||
|
# Move the timer job to an executable async job, then execute it — firing the non-interrupting event
|
||||||
|
# without depending on the async executor's schedule.
|
||||||
|
flcurl -X POST "$fl_base/management/timer-jobs/$timer_id" -H 'Content-Type: application/json' -d '{"action":"move"}' >/dev/null
|
||||||
|
async_id="$(flcurl "$fl_base/management/jobs?processInstanceId=$pid3" | first_job_id)"
|
||||||
|
[ -n "$async_id" ] || { echo "FAIL — timer job did not become an executable job" >&2; exit 1; }
|
||||||
|
flcurl -X POST "$fl_base/management/jobs/$async_id" -H 'Content-Type: application/json' -d '{"action":"execute"}' >/dev/null
|
||||||
|
echo ">> timer fired; the BeoordelingEscaleren token is parked for the domain worker"
|
||||||
|
|
||||||
|
echo ">> polling until the escalation worker reassigns the beoordeling to the teamlead"
|
||||||
|
escalated=""
|
||||||
|
for _ in $(seq 1 30); do
|
||||||
|
groups="$(flcurl "$fl_base/runtime/tasks/$task_id3/identitylinks" 2>/dev/null | candidate_groups || true)"
|
||||||
|
[ "$groups" = "teamlead" ] && { escalated=1; break; }
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
[ -n "$escalated" ] || { echo "FAIL — Beoordelen task not reassigned to teamlead (candidate groups: '$groups')" >&2; docker logs "$dom" 2>&1 | tail -15 >&2; exit 1; }
|
||||||
|
echo "OK — the 14-day timer escalated the still-open Beoordelen task to the teamlead"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user