USER>do $system.OBJ.UnCompile("util.*")

Uncompiling class util.Test
Uncompiling class util.TestGenerator
USER>do ##class(util.Test).TestOneDoSomethingElse()

DO ##CLASS(util.Test).TestOneDoSomethingElse()
^
<CLASS DOES NOT EXIST> *util.Test
USER>do ##class(util.TestGenerator).Generate()

DO ##CLASS(util.TestGenerator).Generate()
^
<CLASS DOES NOT EXIST> *util.TestGenerator
USER>do $system.OBJ.Compile("util.*")

Compilation started on 06/12/2018 14:31:01 with qualifiers ''
Compiling 2 classes, using 2 worker jobs
Compiling class util.TestGenerator
Compiling routine util.TestGenerator.1
Compiling class util.Test
Compiling routine util.Test.1
Compilação terminou com sucesso em 0.050s.

USER>do ##class(util.Test).TestOneDoSomethingElse()

DO ##CLASS(util.Test).TestOneDoSomethingElse()
^
<METHOD DOES NOT EXIST> *TestOneDoSomethingElse,util.Test

I did exactly as you!

When you first imported the class, did you compile it?

If so, maybe Caché had already written the new methods and when you compiled throught terminal It worked.

Try to remove the methods " TestOneDoSomethingElse" and " TestTwoDoSomethingElse" and compile the class again. Check it out if it generates the source correctly

Class util.Test [ DependsOn = util.TestGenerator ]
{

ClassMethod TestOne()
{
    Write 1
}

ClassMethod TestTwo()
{
    Write 1
}

ClassMethod GenerateMethods() As %Status [ CodeMode = objectgenerator ]
{
    For i=1:1:%class.Methods.Count() {
        #dim method As %Dictionary.MethodDefinition = %class.Methods.GetAt(i)
        Continue:((method.Description["@AutoGenerated") || (method.CodeMode="objectgenerator"))
        Do %class.Methods.Insert(##class(util.TestGenerator).Generate(method.Name_"DoSomethingElse",%class.Name))
    }
    Do %class.%Save()
}

}



Class util.TestGenerator
{

ClassMethod Generate(
methodName,
parentName) As %Status
{
    #dim sc As %Status = $$$OK
    Set methodKey = parentName_"||"_methodName
    
    Set newMethod = ##class(%Dictionary.MethodDefinition).%OpenId(methodKey)
    If '$ISOBJECT(newMethod){
    Set newMethod = ##class(%Dictionary.MethodDefinition).%New()
    }
    
    Do newMethod.Implementation.WriteLine($CHAR(9)_"Write """_methodKey_"""")
    Set newMethod.Name = methodName
    Set newMethod.ClassMethod=1
    Do newMethod.parentSetObjectId(parentName)
    Set newMethod.Description = "@AutoGenerated"
    Return newMethod
}

}

When I compile the code, It generates  correctly.

/// @AutoGenerated
ClassMethod TestOneDoSomethingElse()
{
Write "util.Test||TestOneDoSomethingElse"
}

/// @AutoGenerated
ClassMethod TestTwoDoSomethingElse()
{
Write "util.Test||TestTwoDoSomethingElse"
}

but if you see the source,  It is not compiled

 ;util.Test.1
 ;(C)InterSystems, generated for class util.Test. Do NOT edit. 06/12/2018 02:01:03PM
 ;;7735656A;util.Test
 ;
zTestOne() public {
    Write 1 }
zTestTwo() public {
    Write 1 }

When I compile for the second time:

 ;util.Test.1
 ;(C)InterSystems, generated for class util.Test. Do NOT edit. 06/12/2018 02:04:31PM
 ;;4C617153;util.Test
 ;
zTestOne() public {
    Write 1 }
zTestOneDoSomethingElse() public {
Write "util.Test||TestOneDoSomethingElse" }
zTestTwo() public {
    Write 1 }
zTestTwoDoSomethingElse() public {
Write "util.Test||TestTwoDoSomethingElse" }

Hi Eduard.

It did not work neither with a single-process. sad

UPD. Who throws a RESJOB? Do you want to kill compile process from external process (that was my idea)?

Exactly! At first we just want to have some basic page interface to start/stop the script.

Anyway you caught the idea. It is totally related to continuous integration. I'll take a loot at your articles.

Thank you

Hi Rubens,

Thank you for your reply.

The idea was just monitor locks to identify which locks were made by each routine and gets its respective stack, without throwing an exception.

Sometimes we get some lock errors while manipulating persistent classes, and the cause is that other process holds a lock for too long, but we don't have how to identify the reason unless we run ^JOBEXAM right before the error happens