We had a situation where a client-server user has been working for a couple of hours with an open transaction.
After he finished he closed the application and everything was undone.
I would like to create a bad behaving procedure that leaves a transaction open while returning control to the caller.
This proves to be harder than I imagined,
I now have a persistent procedure that creates a record in the main block on a globally scoped buffer but this does not leave a transaction open.
I tried creating the record in internal procedures, doing excluive-find in an internal procedure
None of these actions leave the transaction op after the call finishes
Below is the code I have so far. I would have hoped this was sufficently bad but transaction is false
run devtools/transactiontrouble-l.p persistent. run trouble_exclusivefind. message "transaction" transaction.
block-level on error undo, throw. define buffer global_CCECONV for CCECONV. run cleanup_previous. session:add-super-procedure(this-procedure). /* self-register as super procedure */ /* find first global_CCECONV /* ensure scope is procedure-wide */ where global_CCECONV.AP-NR = 0 and global_CCECONV.CONV-CODE = this-procedure:file-name share-lock.*/ create global_CCECONV. run trouble_starttransaction. procedure cleanup_previous: define variable lHandle as handle no-undo. define variable lCount as integer no-undo. do lCount = 1 to num-entries(session:super-procedures): lHandle = widget-handle(entry(lCount, session:super-procedures)). if lhandle:filename = this-procedure:filename then do: apply "close" to lHandle. delete procedure lHandle. end. end. end procedure. procedure trouble_exclusivefind: find first global_CCECONV where global_CCECONV.AP-NR = 0 and global_CCECONV.CONV-CODE = this-procedure:file-name exclusive-lock. end procedure. /** * Purpose: Start a transaction and leave it open * Notes: * */ procedure trouble_starttransaction: on write of cceconv old OLD-cceconv override do: end. assign global_CCECONV.AP-NR = 0 global_CCECONV.CMP-ID = next-value(CCECONV-ID) global_CCECONV.CRE-WHO = userid("LISA") global_CCECONV.CRE-DAT = today global_CCECONV.CONV-CODE = this-procedure:file-name global_CCECONV.CONV-CCE-V = ? global_CCECONV.CRE-TIME = time global_CCECONV.CONV-TYPE = "trouble" . end procedure. /** * Purpose: Undo the transaction * Notes: * @param parameter1 Description * @return */ procedure trouble_undotransaction: end procedure.
Has somebody created such a procedure that he/she can share ?
Any hints on how to cause an open transaction ?
Transactions should end when the iteration of the block they are scoped to ends.
Given that, it shouldn't be possible for a (sub)transaction started in a callee to still be active when control gets back to the caller -> the callee and any blocks it contains will have moved out of scope at that point.
(Side note: If the buffers used in a tranaction do remain in scope when the transaction ends, locked records won't be released; they'll move to downgraded share-locks instead. That can cause other issues.)
Whatever the issue was, it's most likely that the bad transaction was opened earlier on the call stack than the program the user was actually using to interact with the data.
|
||||
Brian Maher
|
||||
Principal Engineer, Technical Support
|
||||
Progress
|
||||
14 Oak Park | Bedford, MA 01730 | USA
|
||||
|
||||
|
Transactions should end when the iteration of the block they are scoped to ends.
Given that, it shouldn't be possible for a (sub)transaction started in a callee to still be active when control gets back to the caller -> the callee and any blocks it contains will have moved out of scope at that point.
(Side note: If the buffers used in a tranaction do remain in scope when the transaction ends, locked records won't be released; they'll move to downgraded share-locks instead. That can cause other issues.)
Whatever the issue was, it's most likely that the bad transaction was opened earlier on the call stack than the program the user was actually using to interact with the data.
> On Aug 2, 2019, at 5:10 AM, cverbiest wrote:
>
> Any hints on how to cause an open transaction ?
>
>
>
>
in the main procedure, update a record, then call a sub-program that does more stuff and contains code that waits for user input. then user goes on vacation.
main.p:
define buffer c for customer.
find c 1.
c.postal-code = 12345.
run sub.p
sub.p:
find last customer.
update customer.
I was hoping there was a way to test this without causing a transaction higher in the call stack.
But I'm glad there isn't.
Thanks to all who replied