検索

記事
· 2025年3月5日 8m read

How to set up an IRIS Sharding cluster in less than a minute

In this article I'll show you how to set up in your laptop, very quickly, a cluster of IRIS nodes in sharding. It's not the goal of this article neither to talk about sharding in detail nor define a deployment of a production ready architecture, but to show how to set up quickly, in your own machine, a cluster of IRIS instances configured as shard nodes, with which you'll able to play and test this functionality. If you're insterested in knowing more about sharding in IRIS, take a look at the documentation clicking here.  

First and foremost, I want to remark that IRIS sharding will allow us 2 things:

  • Define, load and query shard tables, which data will be distributed transparently between the cluster's nodes
  • Define  federated tables, which offer a global and composed view of data belonging to different tables that will be physically stored in different distributed nodes

So, as I said, we let for other article playing with shard or federated tables, and just focus now in the previous step, that is, setting up the cluster of shard nodes.

Well, for our example we're going to use Docker Desktop (for Windows or MacOS) and we will make use of an IRIS feature: CPF Merge; which allow us to use a plain text file within which we'll include IRIS sections/configuration properties that we want to apply to update the default configuration of an IRIS instance. Basically this file overwrites some parts of the iris.cpf file that defines the default configuration of the instance.

This merging is "triggered" automatically when we add the environment variable: ISC_CPF_MERGE_FILE and it's set with a valid path to a file that contains those sections of the cpf file that we want to change. When IRIS starts, it checks if there is a merge file to apply (basically, if it exists that environment variable and points to a valid file). If so, do the merge and starts.

I won't ramble on, here is the file docker-compose.yml that'll do the magic:

 
docker-compose.yml

Here you have also an example of CSP.conf and CSP.ini files:

 
CSP.conf
 
CSP.ini

In this example, we're instantiating 3 services:

  • irisnode1 - First node of the cluster, it has a special role, that's the reason we named it as node1
  • irisnode2 - Data node, an aditional node to the cluster, which role is data (we can have as many as we want of these)
  • webgateway - Webserver preconfigured to access the IRIS instances (Apache + Webgateway)

To build the image shardnode:latest, I've used the dockerfile below:

 
Dockerfile

Within the dockerfile we call this generic iris.script that would allow us to run ObjectScript code, to setup, import & compile code, etc.., in the IRIS image we're building:

 
iris.script

The files used for the CPF merge for nodo1 and the other IRIS cluster data nodes are:

 
merge_first_data-node.cpf
 
merge_data-node.cpf

We could have more nodes of type data as part of the cluster only adding additional services with the same definition that we have for irisnode2 (changing the name of course)

One more thing, in order to make our routing definition in the webserver to work properly, and so being able to access the System Management Portals for each instance, we have to change the parameter CSPConfigName in each one of them, and we do that with scripts in the files: configure_first_data-node.sh y configure_data-node.sh; for this example both are equal, but I've leave them as separated files because, at some point, we could want to execute different actions for each IRIS instance during start time, depending on if it's a cluster node of type nodo1 or type data.

 
configure_data-node.sh

And that's basically it.

You could define the nodes using the available API in %SYSTEM.Cluster class, but the truth is that the possibility of introducing actions altogether with the CPF Merge feature simplifies the task a lot. I recomend you to take a look at here, in particular at the part referred to the section [Actions].

To build the images and deploy the cluster, we could build our image sharnode:latest and launch our docker-compose from VS Code. Alternately we could do it in our command line, from within the folder in which we have the file: docker-compose.yml, executing these commands:

docker compose build
docker compose up

It'll take a bit the first time because the instance tagged as node1 has to start before whatever other data node in the cluster starts. But everything should be ready and working in 1 minute or less.

If everything went right, you should be able to access to the SMPs of each instance with the URLs below:

And, done! From here, the limits regarding DDBB storage and tables size it's determined by your hardware. You would have and IRIS cluster with sharding enabled to define your shard and/or federated tables.

Hope it's useful for you!! See you around... 

1 Comment
ディスカッション (1)1
続けるにはログインするか新規登録を行ってください
質問
· 2025年3月5日

Enable/Disable a scheduler task

Hi ,

I have a scheduler task and an associated class that works.

Class Sample.Util.CreateTask Extends (%SYS.Task.Definition, %Persistent)
{

Parameter PROPERTYVALIDATION = 1;

Parameter TaskName = "Sample.Util.CreateTask";

Method OnTask() As %Status
{
// Perform the logic
}

}

Is there a way to Enable or Disable the above task "CreateTask()" from an external function/Method/class ?

2 Comments
ディスカッション (2)1
続けるにはログインするか新規登録を行ってください
記事
· 2025年3月4日 2m read

ObjectScriptを使用し、ローカルファイルを他のサーバーにアップロード(POST)する方法

これは InterSystems FAQ サイトの記事です。
 

ObjectScriptの%Netパッケージのライブラリクラスを利用して、ファイルを他のサーバーにアップロードすることができます。

以下のCurl コマンドと同じことを ObjectScript で実現する方法を紹介します。

curl -X POST "http://localhost/api/upload/csv?a=123&b=999" -F file=@"C:/temp/a.csv":/temp/a.csv"

クライアントのObjectScriptコードを以下の様に作成します。

Class User.MyRestClient Extends %Base
{

ClassMethod readMimeData() As %Status
{
    // form-data (for CSV)
    set msg= ##class(%Net.MIMEPart).%New()

    set msg.ContentType = "multipart/form-data"
    set inputstream=##class(%Stream.FileBinary).%New()
    set sc=inputstream.LinkToFile("c:¥temp¥a.csv")
    If $$$ISERR(sc) Do $system.OBJ.DisplayError(sc) Quit
    set filePart = ##class(%Net.MIMEPart).%New(inputstream)
    set filePart.ContentType = "text/csv; charset=utf-8"
    do filePart.SetHeader("Content-Disposition","form-data; name=""csvfile""; filename=""upload.csv"";")
    do msg.Parts.Insert(filePart) 
    set tempstream = ##class(%Stream.TmpCharacter).%New()

    set writer = ##class(%Net.MIMEWriter).%New()

    do writer.OutputToStream(.tempstream)

    do writer.WriteMIMEBody(msg)

    // POST with the above form-data
    set req=##class(%Net.HttpRequest).%New()

    set req.Server="127.0.0.1"
    set req.Port=80
    do req.SetParam("a","123")   ;; a=123
    do req.SetParam("b","999")   ;; b=999
    set req.EntityBody = tempstream

    set req.ContentType = "multipart/form-data; boundary="_msg.Boundary

    set sc = req.Post("/api/upload/csv")

    If $$$ISERR(sc) Do $system.OBJ.DisplayError(sc) Quit
    set res=req.HttpResponse

    write res.Data.Read(1000)
    quit $$$OK
}

}
ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2025年3月4日

Debugging embedded python library

I have an Embedded Python method, which is essentially a call to one third-party module.

Most of the time, the method takes <0.1 seconds to execute, but sometimes it takes 30 or 60 seconds.

The server is relatively idle (20-30% CPU load).

How can I debug this issue further? Ideally, I want to know where this library spends the time. The library is mainly Python code (it's boto3, so it's not a Python C API proxy library).

2 Comments
ディスカッション (2)2
続けるにはログインするか新規登録を行ってください
質問
· 2025年3月4日

Using Lists and ListFind within BPL

I already mentioned in a Previous post I am trying to build a list from a repeatable field within a HL7 message. I figured out how to build the list by using a context list string variable within the Business Process (BPL) and doing a

do context.<variable>.Insert = <value>

 when I am looping through the field. I want to do it one step farther though... I want to search the list to see if the value exists before I do the insert. I only want to insert if the value is different than what is in the list already.

IF $LF(context.Facilities,##class(Ens.Rule.FunctionSet).SubString(context.EpicDepartmentID,1,4)) = 0
{
do context.Facilities.Insert = ##class(Ens.Rule.FunctionSet).SubString(context.EpicDepartmentID,1,4)
}

I tried using $LF or $LISTFIND, but I keep getting the same error...

ERROR <Ens>ErrBPTerminated: Terminating BP EpicMFNToCPD # due to error: ERROR <Ens>ErrException: <LIST>S36+3 ^osuwmc.Epic.MFN.EpicMFNToCPD.Thread1.1 -- logged as '-'
number - @'
IF $LF(context.Facilities,##class(Ens.Rule.FunctionSet).SubString(context.EpicDepartmentID,1,4)) = 0'
> ERROR <Ens>ErrException: <LIST>S36+3 ^osuwmc.Epic.MFN.EpicMFNToCPD.Thread1.1 -- logged as '-'
number - @'
IF $LF(context.Facilities,##class(Ens.Rule.FunctionSet).SubString(context.EpicDepartmentID,1,4)) = 0'

Any guidance would be appreciated.

1 Comment
ディスカッション (1)1
続けるにはログインするか新規登録を行ってください