go to post Dmitrii Baranov · Jul 16 Hi Tani and thanks a lot for the info! To avoid struggling with interprocess communication, I experimented a little more and ended up with Workers and Python (see below). I'd appreciate your opinion
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 · Jul 16 Hi Alexey, that's the point! I expect the following sequence: - the worker is created in background and waits for, say, 5 seconds. The main thread isn't blocked! - the program prints "This should be printed first" - the waiting interval of 5 seconds expires and the worker emits its own message
go to post Dmitrii Baranov · Jul 16 Hi Timo, Yesterday I experimented a lot with both Python and workers (and failed). Here is an example. In this code I want the workers to be started as background tasks, so the program should first print "This should be printed first", then each worker (each started with random delay interval) shoud print its own message. This obviously doesn't happen because of the queue.Sync() call but I don't want to wait for all the workers to complete. Class DelayedTest Extends %RegisteredObject { ClassMethod Callback(interval As %String) As %Status { Hang interval Write "Interval = ", interval, ! Return $$$OK } Method RunWorkers() { #Dim queue as %SYSTEM.WorkMgr Set queue = ##class(%SYSTEM.WorkMgr).%New() For i = 1:1:5 { Set status = queue.Queue("..Callback", $RANDOM(5) + 1) // Minimal delay is 1 second $$$ThrowOnError(status) } Set status = queue.Sync() $$$ThrowOnError(status) } ClassMethod Main() { #Dim d = ##class(DelayedTest).%New() Do d.RunWorkers() Write "This should be printed first" } } Also, I'm not sure that Hang is appropriate here to emulate some delay. If it works like Sleep it should block the main thread.
go to post Dmitrii Baranov · Mar 23 Anyone who has experience converting, say, HL7 v2 ORU into a complex FHIR Bundle will never ever use DTL
go to post Dmitrii Baranov · Mar 11 The most popular OpenEHR GitHub repositories have 200-300 stars... No one uses it and no one needs it
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 · Jan 10 I faced similar issues with Postgres linked tables because of different SQL syntax and also poorly implemented translation from IRIS dialect to your linked server dialect. The workaround is to add an instance of EnsLib.SQL.Operation.GenericOperation to your production and to execute SQL queries via ODBC/JDBC bypassing IRIS, something like: Set operation = ##class(EnsLib.SQL.Operation.GenericOperation).%New("NameOfYourProductionComponent") #Dim rs as EnsLib.SQL.GatewayResultSet Set status = operation.Adapter.ExecuteQuery(.rs, "select 1", .args) While (rs.Next()) { ... } Do rs.Close()
go to post Dmitrii Baranov · Dec 30, 2024 I believe Spotify exposes a standard OAuth2 endpoint so you can use built-in IRIS classes to deal with tokens (but to be honest the standard library looks overcomplicated so I personally often use the same approach)
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 17, 2024 `..FindPoolIndex` doesn't exist, it's pseudocode (by the way, ChatGPT has very little and poor knowledge about IRIS)
go to post Dmitrii Baranov · Dec 17, 2024 No, it is a Postgres linked table, but it is not really important, I just want to parallelize the process
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
go to post Dmitrii Baranov · Dec 10, 2024 To be honest... no :) Actually I think I badly need a standalone terminal (but Studio is discontinued) or a Python/Java/C#/whatever library which is able to invoke arbitrary commands on a remote server and I'm just wondering if such libraries exist. PS leveraging WebTerminal API looks attractive but it seems to me it doesn't expose Swagger/OpenAPI definitions
go to post Dmitrii Baranov · Dec 1, 2024 That's probably the point. You are right, it is a containerized instance. Thanks again
go to post Dmitrii Baranov · Dec 1, 2024 Great, thanks a lot, it works. The real error messages are "ERROR #6162: Unable to create HTTP Authorization header for NTLM scheme." and "ERROR #6162: Unable to create HTTP Authorization header for Negotiate scheme." for both NTLM and Negotiate schemes respectively. Does it mean that IRIS is unable to deal with these authentication schemes? The documentation says that NTLM is supported.
go to post Dmitrii Baranov · Nov 18, 2024 Hi Timo,and thanks a lot, I've disabled the FastDistinct so now everything works as expected. Your link took me to a page that describes the Group By operator and it happened so this "feature" is documented and that another option is to use the %Exact function, e.g. select distinct %Exact(value) ...
go to post Dmitrii Baranov · Nov 17, 2024 Hi Tani, in most cases the stream contains JSON. The container definition looks like: Class MyRequest Extends (Ens.StreamContainer, %JSON.Adaptor) { } I just want the stream content to be rendered always
go to post Dmitrii Baranov · Nov 2, 2024 I'm sorry for the false alarm. I've increased the FHIR server "Max Search Results" option value so now everything works fine.
go to post Dmitrii Baranov · Oct 21, 2024 The option with $LIST(...) works, thanks again (not so elegant though but OK as a workaround). I'm thinking about registering a feature request.