How should we make long-running transaction "integrity error" free while using Django? (especially foreignkey integrity error)
Our application has entity 'A' and 'B' (for the sake of simplicity) which has following semantics.
'B' has a foreign key field that points to 'A'.
Periodically, multiple 'B' (in 100s of thousands) get created when a event take place.
Creation of the multiple 'B's should be always transactional, in that we should always build all of the 'B's or nothing so that in case of error, we can re-trigger the event.
Intermittently, some 'A' may get destroyed. In other words, we cannot control the lifecycle of the 'A'.
I am currently using django's basic transaction functionality (transaction.atomic) to ensure 'B's atomic creational behaviour.
Since building 'B's take some time (1 hour or so), if some of the 'already-referenced' 'A' gets deleted in the meantime, whole transaction fails with the ForeignKey integrity error.
For the sake of clarity, if I may explain with crude diagram.
Following Bi's get created sequentially,
[ B1 (references A1), B2 (references A2) ....... Bn (references An) ] tries to transact the whole operation only when created all of the B1...Bn.
While creating Bm (1 <= m < n) Ak (1 <= k < m) gets destroyed and the results are committed to database, thus leading to raise ForeignKey integrity error, only when we built all of the Bs (after an hour), and fails.
If controlling the lifecycle of the 'A' were so easy, then this won't be a problem. If time for building multiple 'B's were so short, then this won't be a problem.
Since building 'B' take so much time, re-trying only after we find integrity error doesn't work well in the production environment.
In the best case scenario, It would be great if integrity error is suppressed and wrongful row gets silently deleted, the row which references already deleted 'A'.
I am currently using Django with Postgre. Any comment is greatly appreciated.
Another requirement is that locking table "A" (whether it is table-level or row-level) shouldn't be used since querying, modifying, and inserting (except for delete) operation should be made available regardless of whether I build "B" or not. "A" is a user information table, which should be open to alteration anytime (We can defer the deletion if needed)