La citazione menziona non solo respinta ma rifiutata per attraversare oltre il limite. Ciò corrisponde al caso in cui un token non è autorizzato a passare attraverso un bordo e non al caso in cui un bersaglio potrebbe non accettarlo.
In tal caso viene respinto per attraversamento?
Sfortunatamente, a differenza dei termini offerti e accettati che sono ben definiti, il termine respinto non è esplicitamente definito e deve essere interpretato.
Per quanto ne so, può succedere solo nel caso di una guardia, come descritto in 15.2.3.3
:
An ActivityEdge may have a guard, which is a ValueSpecification that
is evaluated for each token offered to the edge. An offer shall only
pass along an ActivityEdge if the guard for the edge evaluates to true
for the offered token.
In tal caso non viene rifiutato per attraversamento?
Per peso, non c'è attraversata respinta. I token vengono accumulati nella sorgente fino a quando non viene raggiunta la soglia. Nel caso in cui una guardia blocchi un token, non è l'attraversamento che fallisce ma l'offerta:
If the guard fails for any of the tokens, and this reduces the number
of tokens that can be offered to the target to less than the weight,
then all the tokens fail to be offered.
Per la selezione non c'è anche il rifiuto di un attraversamento, ma un ritardo all'accettazione ( 15.2.3.4
):
selection Behavior is used while offering tokens to the target node,
it may be run many times on the same token before the token is
accepted by the target node.
Ulteriori osservazioni su 15.3.3.4 e risoluzione del tuo scenario
La seguente dichiarazione ci dice che in caso di attraversamento respinto, il token è definitivamente ritirato:
If tokens are rejected for traversal, they shall no longer be offered
to the outgoing edge.
La seguente dichiarazione ci dice che, a meno che un token non venga respinto per attraversarlo, aspetterà che venga accettato dal target (l'accettazione non deve essere immediata):
They shall be accepted by the target or rejected for traversal over
the edge
Conseguenza: nel tuo scenario, b
attenderà a
e verranno entrambi consumati insieme per generare un token di output del nodo di join corretto.
E infine, questa frase spiega che in caso di attraversamento riuscito, i token vengono inviati in sequenza, uno per uno:
before any more tokens are offered to the outgoing edge
Conseguenza: nel tuo scenario, fintanto che b
aspetterà un a
, nessun nuovo b
sarà offerto dal join di sinistra.
Modifica: non c'è un problema con le specifiche UML qui?
La regola "uno per uno" non sembra completamente coerente. IMHO:
- La regola è scritta sulla parte offerta sull'output, non sulla parte di consumo dell'input. Questo rende il comportamento in caso di un peso sull'output estremamente ambiguo: lo eviterei.
- La regola sembra scritta con i token di controllo in mente. Non mi è chiaro cosa succederà se sull'input sono presenti 2 diversi token oggetto (o 2 oggetti replicati senza CombinedDuplicates): mi aspetterei che tutti passino il join. Ma cosa succede se uno di questi viene rifiutato: l'altro continuerà la sua strada da solo?
Allo stesso modo, IMHO il rifiuto sulla logica trasversale non sembra coprire tutti i casi. Ad esempio, cosa succede se il limite di uscita passa a un nodo decisionale (quindi non viene rifiutato), ma nessuno dei successivi rami custoditi può accettarlo? Comprendiamo che il token è stato rifiutato (implicitamente l'input della decisione sarebbe protetto dalla combinazione di tutti i possibili output), o dovremmo considerarlo consumato e il token è in attesa nel nodo decisionale?
Quindi penso che ci sia ancora del lavoro da fare per il comitato standard in questo settore.