How to force an open transaction for test purposes

Posted by cverbiest on 02-Aug-2019 09:08

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 ?

Posted by frank.meulblok on 02-Aug-2019 10:59

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.

All Replies

Posted by Brian K. Maher on 02-Aug-2019 10:16

Hi Carl,
 
Try something like this:
 
/* test.p */
 
run procx in this-procedure.
 
procedure procx:
    find first customer exclusive-lock.
end procedure.
 
 
Brian Maher
Principal Engineer, Technical Support
Progress
Progress
14 Oak Park | Bedford, MA 01730 | USA
phone
781-280-3075
Twitter
Facebook
LinkedIn
Google+
 
 

Posted by frank.meulblok on 02-Aug-2019 10:59

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.

Posted by gus bjorklund on 02-Aug-2019 13:42

> 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.

Posted by cverbiest on 07-Aug-2019 12:42

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

This thread is closed