go to post Dmitrii Baranov · Jul 16 I finally managed to solve the problem in Python. It's not perfect but it works: Class User.Timer Extends %RegisteredObject { Property Executor [ Private ]; Method Initialize(maxWorkers As %Integer = 4) [ Language = python ] { import concurrent.futures import time import threading self.Executor = concurrent.futures.ThreadPoolExecutor(max_workers=maxWorkers) } Method Close() [ Language = python ] { if self.Executor: self.Executor.shutdown() } Method Greet(name) { Write "Hello ", name, ! } Method OnCallback0(methodName As %String) [ Private ] { Do $METHOD(instance, methodName) } Method OnCallback1(instance As %RegisteredObject, method As %String, arg1) [ Private ] { Do $METHOD(instance, method, arg1) } Method OnCallback2(instance As %RegisteredObject, method As %String, arg1, arg2) [ Private ] { Do $METHOD(instance, method, arg1, arg2) } Method OnCallback3(instance As %RegisteredObject, method As %String, arg1, arg2, arg3) [ Private ] { Do $METHOD(instance, method, arg1, arg2, arg3) } Method OnCallback4(instance As %RegisteredObject, method As %String, arg1, arg2, arg3, arg4) [ Private ] { Do $METHOD(instance, method, arg1, arg2, arg3, arg4) } Method OnCallback5(instance As %RegisteredObject, method As %String, arg1, arg2, arg3, arg4, arg5) [ Private ] { Do $METHOD(instance, method, arg1, arg2, arg3, arg4, arg5) } Method InternalRun(delayMs As %Integer, wait As %Boolean, instance As %RegisteredObject, method As %String, args... As %List) [ Internal, Language = python ] { import time import iris if not self.Executor: raise Exception("The 'Initialize' method has not been called.") def worker_function(): time.sleep(delayMs / 1000) if len(args) == 0: self.OnCallback0(instance, method) elif len(args) == 1: self.OnCallback1(instance, method, args[0]) elif len(args) == 2: self.OnCallback2(instance, method, args[0], args[1]) elif len(args) == 3: self.OnCallback3(instance, method, args[0], args[1], args[2]) elif len(args) == 4: self.OnCallback4(instance, method, args[0], args[1], args[2], args[3]) elif len(args) == 5: self.OnCallback5(instance, method, args[0], args[1], args[2], args[3], args[4]) else: raise Exception("Too many arguments.") return 0 future = self.Executor.submit(worker_function) # wait == 0 means fire-and-forget try: if (wait == 1): rv = future.result() except Exception as e: print(f"{e}") } /// delayMs - the parameter specifies the timer delay in milliseconds /// wait - if the parameter is false, the process will not wait for the Future result to be returned (fire-and-forget) /// instance - any object which method should be called with a delay /// method - specifies the object's callback method name /// args - the callback method arguments (up to 5) Method Run(delayMs As %Integer, wait As %Boolean, instance As %RegisteredObject, method As %String, args... As %List) { Do ..InternalRun(delayMs, wait, instance, method, args...) } ClassMethod Test() { Set obj = ##class(Timer).%New() Do obj.Initialize() Do obj.Run(1000, 0, obj, "Greet", "John") Do obj.Run(2000, 0, obj, "Greet", "Jessica") Write "If 'wait == 0' this line will be printed first", ! Do obj.Close() } }
go to post Dmitrii Baranov · Feb 25 Here it is (implemented as Mixin): Class MyNamespace.Pooled Extends Ens.Host [ Abstract ] { Property PoolIndex As %Integer [ Calculated ]; Method PoolIndexGet() As %Integer { #Dim cn as %String Set cn = ..%ConfigName #Dim statement as %SQL.Statement Set statement = ##class(%SQL.Statement).%New() Set status = statement.%PrepareClassQuery("Ens.Job","Enumerate") $$$ThrowOnError(status) #Dim rs as %SQL.StatementResult Set rs = statement.%Execute() #Dim i as %Integer = -1 While (rs.%Next()) { #Dim jobId as %String Set jobId = rs.%Get("Job") If (rs.%Get("ConfigName") = cn) { Set i = i + 1 If (jobId = $JOB) { Kill rs Return i } } } Kill rs Return i } Property PoolSize As %Integer [Calculated]; Method PoolSizeGet() As %Integer { #Dim cn as %String Set cn = ..%ConfigName #Dim statement as %SQL.Statement Set statement = ##class(%SQL.Statement).%New() Set status = statement.%PrepareClassQuery("Ens.Job","Enumerate") $$$ThrowOnError(status) #Dim rs as %SQL.StatementResult Set rs = statement.%Execute() #Dim i as %Integer = 0 While (rs.%Next()) { If (rs.%Get("ConfigName") = cn) { Set i = i + 1 } } Kill rs Return i } }
go to post Dmitrii Baranov · Dec 28, 2024 Found the answer. It is simply not allowed: "+ Rule: For collections of type document, message, searchset or collection, all entries must contain resources, and not have request or response elements"
go to post Dmitrii Baranov · Dec 14, 2024 The error has gone after IRIS restart. Another indicator of the problem was that the SQL Gateway connection test was not working