With invalidation caches, Infinispan 2LC records information that an entity/collection is being invalidated in pending-puts cache before the transaction, starting from EntityRegionAccessStrategy.insert/update and then wipes that information after the transaction is committed from EntityRegionAccessStrategy.afterInsert/afterUpdate. However, when the transaction is rolled back, these after* methods are not called and the invalidation info leaks on the node that executes the transaction.
This does not cause several memory issues as the PutFromLoadValidator removes old invalidation records, but during this time the entry is not loaded from cache, which has a negative performance impact.
With transactional invalidation caches, Infinispan is registered as a synchronization and it could be possible to remove the invalidation info during roll back (it sends a command releasing the invalidation to other nodes), but on local node the Session is used as a session/transaction identifier, while remote nodes we use global transaction ID (Infinispan identifier for the transaction). The Session object is not available to Infinispan during rollback handling, therefore we would have to use global transaction ID for the local call to PutFromLoadValidator.beginInvalidatingKey - though, that means that this call would have to move inside the Infinispan interceptor stack.
Alternative is a registration of another synchronization explicitly from the insert/update call and ignore the after* methods, but that brings additional overhead to successful transactions.