How to terminate a process without rollback
Hi Community,
When we terminate a process that is in a transaction, the system (fortunately) performs a rollback.
As part of some troubleshooting, I'm wondering if there's a way around this behavior to avoid rollback (or force commit) before termination.
Recently we had an issue on a test server with a process stuck in a huge transaction (around 100GB).
The out-of-control process was suspended and then terminated causing a rollback.
In the case of a test server, this is not really a problem.
If it happens on a production system, depending on the situation we might prefer to avoid rollback (journal volume, server availability, performance...).
We can suspend the process to save time, but then how to terminate it and avoid the rollback.
Although not recommended for obvious reasons, Is it possible?
Thank you.
Comments
It is rather brute force but matches your decision to skip rollbacks:
while $TLEVEL { TCOMMIT }to be sure to catch all cases I'd place it in a %ZSTOP.mac
It's the reverse of %ZSTART. >> docu
Hi @Robert Cemper !
Good Idea!
I tested, but unfortunately, It seems already too late, the rollback is already performed.
%ZSTOP routine
ROUTINE %ZSTOP
%ZSTOP
Quit
SYSTEM
Set ^zJob($i(^zJob)) = $ZDATETIME($HOROLOG, 3, 1) _" LABEL-SYSTEM (" _ $JOB _ ") "_$NAMESPACE _ " TLEVEL: "_$TLEVEL
Do ZFORCECOMMIT
Quit
LOGIN
Quit
JOB
Set ^zJob($i(^zJob)) = $ZDATETIME($HOROLOG, 3, 1) _" LABEL-JOB (" _ $JOB _ ") "_$NAMESPACE _ " TLEVEL: "_$TLEVEL
Do ZFORCECOMMIT
Quit
CALLLIN
Quit
ZFORCECOMMIT
If $Data(^zForceCommit($Job)) {
While $TLEVEL {
TCOMMIT
}
}
Quit
Even if the process is in a transaction before "terminate", the ^zJob trace records a $TLEVEL with the value 0.
Maybe it's just not possible (or possible with a not documented procedure).
Thank you.
You are right.
But it works in a test within a Try-Catch bloxk
try {
;;; run your code
}
catch e {
if $ze["<RESJOB>" while $TLEVEL { tcommit }
}This may be useful to you:
Hi @Robert Cemper, @Vitaliy Serdtsev
Thank you for your replies! I found a solution to do this without any change to an existing code, not simple but It works and could be useful in a critical situation.
I read the code of ^%ETN and see these lines :
UserError() s $zt="UserErrorE"
i $d(^rOBJ("%ZERROR")) d
. n %00000 d ^%ZERROR
So, If we create a "%ZERROR" routine, we have an entry point :
ROUTINE %ZERROR
%ZERROR
If $Data(^zForceCommit($Job)) { ; to avoid do this for all processes...
While $TLEVEL {
TCOMMIT
}
}
Quit
And then, we must terminate the process like that:
Set pid = "1234" ; pid to terminate
Set ^zForceCommit(pid)=""
Zn "%SYS"
Set process = ##class(SYS.Process).%OpenId(pid)
Set sc = process.Terminate(1)
It's important to use the SYS.Process class and the Terminate method with argument 1 to use ^%ETN.
GREAT !
without touching the code