Re: Cayenne callback listener in single transaction
Andrus Adamchik <[email protected]>
| Newsgroups | gmane.comp.java.cayenne.devel |
|---|---|
| Message-ID | <[email protected]> |
> On Dec 21, 2019, at 7:55 AM, Aristedes Maniatis <[email protected]> wrote: > > On 19/12/19 1:18am, Artem Kravchenko wrote: >> So the problem which I faced with: the commits (main one and subsequent from listener) are two different jdbs transaction, which is reasonable in fact. But in such case the data consistency is not guaranteed - second commit might be failed. It is really important for me. > > > At first glance, I cannot understand why wrapping them in a single transaction would not be the default behaviour here. Adding records in @PostPersist is likely something like: > > * audit records to track changes > > * financial transactional data (eg writing to a general ledger when invoice is created) > > * updating denormalised data (eg. contact.owing) which might be done for search or performance reasons. > > > In each case I can think of, rolling back the whole transaction would be a more appropriate behaviour in case of failure. > > > Cheers > > Ari IIRC the original thinking was that many "post" operations are not DB-specific (e.g. sending an email, writing to a file, etc). So they are allowed to fail without rolling back the transaction, and may also be slow and needlessly holding the connection. An ideal solution should support both transactional and non-transactional callbacks to allow the user to chose. I guess an extra transaction property on all @Post* annotations may solve this as the expense of a more complicated event dispatch. Open to discussion on this. Also there is an alternative mechanism that has this control already - DataChannelFilter, or its special audit-centric implementation CommitLogFilter [1]. Here is how to register a filter inside or outside a transaction [2]: if (excludeFromTransaction) { ServerModule.contributeDomainSyncFilters(binder) .addAfter(MyFilter.class, TransactionFilter.class); } else { ServerModule.contributeDomainSyncFilters(binder) .insertBefore(MyFilter.class, TransactionFilter.class); } So I hope this solves the immediate problem. Andrus [1] https://cayenne.apache.org/docs/4.1/cayenne-guide/#ext-commit-log [2] https://github.com/apache/cayenne/blob/STABLE-4.1/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java#L117