go to post Eduard Lebedyuk · Feb 5 How about the following setup: In Business Service or first router BP set a global: ^data(mrn, timestamp) = messageId In your FIFO BP before sending to BO check: set nexttimestamp=$o(^data(mrn,""),1,nextmessageId) If nextmessageId equals current messageid that means there's no message in a pipeline for the same patient with earlier timestamp so we can send it out. Kill ^data(mrn, nexttimestamp) so next message can be processed If nextmessageId does not equal current messageid, compare timestamps: If timestamps are equal, send the message anyway and don't kill the subscript - we have more than one message with the same timestamp. If it happens often, value should be a list of ids. If nexttimestamp is earlier than timestamp, it means there are some other messages in a pipeline with the same MRN, sleep for 10 seconds and check again. Notes: You'll need to adjust this based on what you want to do if one of the messages errors before being deleted from the ^data global, options: Processing of messages for this patient effectively stops. Add an additional check in (4) - get other message header and check if it's in a final state (completed, errored, etc) - if so clear ^data subscript and continue. Add an additional check in (4) - if we waited more than X seconds, continue. This can be wrapped as Custom Functions and called from rules, BPs. Locks might help with ensuring consistency. The advantage here is that you can scale to any number of jobs immediately and since you enforce FIFO only at the end, most of the processing can be parallelized.
go to post Eduard Lebedyuk · Jan 31 You'll need to implement %OnValidateObject callback to do custom checking.
go to post Eduard Lebedyuk · Jan 13 PropertyClass is for registered objects, not datatypes themselves.
go to post Eduard Lebedyuk · Nov 8, 2024 Here's how to do it (sample code to transfer files over iris connection): /// Get IRIS connection object /// set iris = ##class().GetIRIS() ClassMethod GetIRIS() As %Net.DB.Iris { Set host = "host" Set port = 1972 Set ns = "%SYS" Set user = "_SYSTEM" Set pass = "***" Set connection = ##class(%Net.DB.DataSource).CreateConnection(host, port, ns, user, pass) Set iris = connection.CreateIris() Quit iris } /// Transfer one file from sourceFile to targetFile on iris connection. ClassMethod Transfer(iris As %Net.DB.Iris, sourceFile As %String, targetFile As %String) As %Status { Set sc = $$$OK Try { Set stream = ##class(%Stream.FileBinary).%New() Do stream.LinkToFile(sourceFile) Set var = "%stream" Do iris.ClassMethodVoid($classname(), "InitStream", var, targetFile) While 'stream.AtEnd { Set chunk = stream.Read($$$MaxStringLength-1000) Do iris.ClassMethodVoid($classname(), "WriteStream", var, chunk) } Do iris.ClassMethodVoid($classname(), "SaveStream", var, ##class(%File).Attributes(sourceFile)) } Catch ex{ Do ##class(%SYS.System).WriteToConsoleLog("SuperServer Copy failure in Transfer:" _ ex.DisplayString()) Throw ex } Quit sc } /// Initialize stream for subsequent write requests and place it in var. /// var must be a global variable (start form %) /// file is created or truncated if already exists ClassMethod InitStream(var As %String, file As %String) { Try { Do ##class(%File).Truncate(file) Set stream = ##class(%Stream.FileBinary).%New() Do stream.LinkToFile(file) Set @var = stream } Catch ex{ Do ##class(%SYS.System).WriteToConsoleLog("SuperServer Copy failure in InitStream: " _ ex.DisplayString()) Throw ex } } /// Wrile string into a stream initialized by InitStream ClassMethod WriteStream(var As %String, string As %String) { Try { Do $method(@var, "Write", string) } Catch ex{ Do ##class(%SYS.System).WriteToConsoleLog("SuperServer Copy failure in WriteStream: " _ ex.DisplayString()) Throw ex } } /// Save stream initialized by InitStream. /// Optionally sets file attributes. ClassMethod SaveStream(var As %String, attributes As %String = "") { Try { Set sc = $method(@var, "%Save") Set file = $property(@var, "Id") Kill @var Do:attributes'="" ##class(%File).SetAttributes(file, attributes) } catch ex { Do ##class(%SYS.System).WriteToConsoleLog("SuperServer Copy failure in Savetream: " _ ex.DisplayString()) Throw ex } } Use ClassMethodValue to get a scalar value back. Use json for complex type transfer as objects are not supported. There are other methods corresponding to APIs in other languages. Also please note that this class (technically only the callee *Stream methods but save yourself a headache and just copy the entire class) needs to be present on both nodes. Finally, remember that callee methods must produce no stdout/stderr writes, since the io is bound to the iris connection itself and it cannot disambiguate stdout.
go to post Eduard Lebedyuk · Sep 9, 2024 $zf should work: w $zf(-100,"/SHELL","eventcreate","/ID",1,"/L","APPLICATION","/T","INFORMATION","/SO","MYEVENTSOURCE","/D","My first log")
go to post Eduard Lebedyuk · Aug 26, 2024 Are you in the interop context? If yes, SendSync/SendAsync should be available for you. If not, check this article.
go to post Eduard Lebedyuk · Jun 10, 2024 Yes, query Ens.MessageHeader table, maybe joining on a body and then call AbortMessage method here.
go to post Eduard Lebedyuk · May 29, 2024 Create subscript level mappings for a correct database. %ALL global mapping is higher priority than namespace mapping: if %ALL has ^a global mapped to db A and your namespace has ^a mapped to db B, global ^a from db A would be used when you access it from your namespace. But, subscript mapping is higher priority than global mapping: if %ALL has ^a global mapped to db A and your namespace has ^a(1) mapped to db B, global ^a(1) from db B would be used when you access ^a(1) from your namespace.
go to post Eduard Lebedyuk · May 8, 2024 Please check this series of articles, it's about git not tfs but the underlying idea is the same.
go to post Eduard Lebedyuk · May 2, 2024 There are two formats for LUT: Old one: <?xml version="1.0" encoding="UTF-8"?> <Export generator="IRIS" version="26" zv="IRIS for UNIX (Red Hat Enterprise Linux 7 for x86-64) 2022.1 (Build 209U)" ts="2024-03-03 06:05:36"> <Document name="LUT_NAME.LUT"> <lookupTable> <entry table="LUT_NAME" key="KEY">VALUE</entry> <entry table="LUT_NAME" key="KEY2">VALUE2</entry> </lookupTable> </Document> </Export> New one: <?xml version="1.0"?> <lookupTable> <entry table="LUT_NAME" key="KEY">VALUE</entry> <entry table="LUT_NAME" key="KEY2">NALUE2</entry> </lookupTable> Looks like you're importing old format using new importer. Here's the code to import both versions: ClassMethod ImportLUT(dir) { #include %occErrors write "Lookup Tables import from: " _ dir set rs = ##class(%File).FileSetFunc(dir, "*.xml;*.XML;*.lut;*.LUT") while rs.%Next() { set tablePath = rs.Get("Name") write "Importing: " _ tablePath,! // table is the full path, the last part (denoted by *) is the actual file name set tablePathNoExtension = $PIECE(tablePath, "/", *) // asking for $PIECE with just delimiter asks for the first part, thus ignore anything after the . set tablePathNoExtension = $PIECE(tablePathNoExtension, ".") write "Importing Lookup Table in " _ tablePathNoExtension,! // lookup table should be named the file name (without extension) //do ##class(Ens.Util.LookupTable).%ClearTable(tablePathNoExtension) // Try the new import first. set sc = ..ImportLUTFile(tablePath) // If we got an error, try legacy import if $$$ISERR(sc) { write "New import failed. Trying legacy import",! set sc=##class(Ens.Util.LookupTable).%Import(tablePath) if $$$ISOK(sc) { write "Import successful",! } } // Error remains unfixed. Fail. if $$$ISERR(sc) { write "Lookup Table import failure: ", $System.Status.GetErrorText(sc),! do $system.Process.Terminate(, 1) } } } /// Adapted from EnsPortal.LookupSettings:Import /// Import lookup tables from file <var>Filename</var> ClassMethod ImportLUTFile(Filename As %String) As %String { Set tRS = ##class(%ResultSet).%New("%RoutineMgr:ImportItemList") Set tSC = tRS.Execute(Filename) Quit:$$$ISERR(tSC) tSC Set tSC = $$$OK Kill Select For { Quit:'tRS.Next(.tSC) Set Name = tRS.Get("Name") If $E(Name,*-3,*)=".LUT" { Lock +^Ens.LookupTable(Name):2 If '$T Set tSC = $$$ERROR($$$LockFailedToAcquireRead,$Name(^Ens.LookupTable(Name))) Quit Set Select($E(Name,1,*-4)) = "" } } Quit:$$$ISERR(tSC) tSC Quit:'$D(Select) $$$ERROR($$$GeneralError,"This file does not contain any lookup tables") Set tSC = $system.OBJ.Load(Filename,"-d", .Err, .Loaded, 0) Set Name = "" For { Set Name = $O(Select(Name)) Quit:Name="" Lock -^Ens.LookupTable(Name) } Quit tSC }
go to post Eduard Lebedyuk · Apr 27, 2024 IRIS supports multiple inheritance for methods, so create an abstract class which holds the methods and add it to a list of superclasses of your production class.
go to post Eduard Lebedyuk · Apr 17, 2024 You need to iterate on value: // extract json content from the request: set dynRequestJsonPayload = {}.%FromJSON(%request.Content) #dim JsonIterator As %Iterator.AbstractIterator set JsonIterator = dynRequestJsonPayload.%GetIterator() // iterate on json structure: if dynRequestJsonPayload '= "" { while JsonIterator.%GetNext(.key, .value, .NodeType) { if NodeType = "string" { do GlobalTrace("NodeType: " _ NodeType _ "; key: " _ key _ "; value: " _ value) } elseif NodeType = "array" { // i want to iterate on this array... // the following line throws the exeception "ERREUR #5002: Erreur ObjectScript: <INVALID OREF>traitementUFI+34^common.REST.1" set JsonIteratorSecondary = value.%GetIterator() } else { // Do something } } }
go to post Eduard Lebedyuk · Apr 16, 2024 Do you have Stay Connected setting equal to -1? Try setting it to a lower value, i.e. 30.