Article Eduard Lebedyuk · Dec 17, 2019 3m read

This series of articles would cover Python Gateway for InterSystems Data Platforms. Execute Python code and more from InterSystems IRIS. This project brings you the power of Python right into your InterSystems IRIS environment:

  • Execute arbitrary Python code
  • Seamlessly transfer data from InterSystems IRIS into Python
  • Build intelligent Interoperability business processes with Python Interoperability Adapter
  • Save, examine, modify and restore Python context from InterSystems IRIS

Other articles

The plan for the series so far (subject to change).

0
0 591
Article Eduard Lebedyuk · Dec 9, 2019 1m read

If you work with anything other than English, you would earlier or later encounter the characters from the title or just plain ??????????.

Encodings are usually known, but sometimes you just get gibberish and need to make sense of it.

In this cases $zcvt is your friend, the three argument form specifically.

But there are a lot of options. So here's an utility script to check how the text would look like in different encodings:

Zn "%SYS"
Set Text = "ÍàØâàÞæØâë"
Set Ref = ##class(Config.NLS.Locales).OpenCurrent(.Sc)
Write "Locale name: ",Ref.Name, !
Do Ref.GetTables(.Tables)
Set Key = ""
For { Set Key = $O(Tables("XLT", Key)) Quit:Key=""  Write Key," ",$zcvt(Text, "I", Key),!}
4
0 460
Article Eduard Lebedyuk · Dec 7, 2019 1m read

%objlasterror is a useful reference to the last error.

Every time $$$ERROR is called, %objlasterror is set to a result of this call.

It's important in cases where you want to convert exception to status:

Try {
   //  quality code
} Catch ex {
   Set sc = $g(%objlasterror, $$$OK)
   Set sc = $$$ADDSC(sc, ex.AsStatus())
}

Because AsStatus calls $$$ERROR under the wraps, the order is important, first you need to get %objlasterror and  convert exception after that.

8
3 1494
Article Eduard Lebedyuk · Dec 3, 2019 1m read

One of the most useful features in Studio is code snippets.

Here's how to add snippets to VSCode.

Here's a generalized instructions.

1. Go to File - Preferences - User Snippets and choose objectscript.

2. Add your snippet, here's an example:

"SQL Statement": {
    "prefix": ["sql"],
    "body": ["#dim rs As %SQL.ISelectResult",
            "set rs = ##class(%SQL.Statement).%ExecDirect(,\"SELECT * FROM\")",
            "while rs.%Next() {",
            "\twrite rs.ID, !",
            "}"]
}
1
5 864
Article Eduard Lebedyuk · Nov 22, 2019 1m read

This quick guide shows how to serve HTTPS requests with InterSystems API Management. Advantage here is that you have your certs on one separated server and you don't need to configure each backend web-server separately.

Here's how:

1. Buy the domain name.

2. Adjust DNS records from your domain to the IAM IP address.

3. Generate HTTPS certificate and private key. I use Let's Encrypt - it's free.

4. Start IAM if you didn't already.

5. Send this request to IAM:

POST http://host:8001/certificates/
{
    "cert": "-----BEGIN CERTIFICATE-----...",
    "key": "-----BEGIN PRIVATE KEY-----...",
    "snis": [
        "host"
    ]
}
2
1 694
Article Eduard Lebedyuk · Nov 20, 2019 9m read

In this article, I would like to talk about the spec-first approach to REST API development.

While traditional code-first REST API development goes like this:

  • Writing code
  • REST-enabling it
  • Documenting it (as a REST API)

Spec-first follows the same steps but reverse. We start with a spec, also doubling as documentation, generate a boilerplate REST app from that and finally write some business logic.

This is advantageous because:

  • You always have relevant and useful documentation for external or frontend developers who want to use your REST API
  • Specification created in OAS (Swagger) can be imported into a variety of tools allowing editing, client generation, API Management, Unit Testing and automation or simplification of many other tasks
  • Improved API architecture.  In code-first approach, API is developed method by method so a developer can easily lose track of the overall API  architecture, however with the spec-first developer is forced to interact with an API from the position if API consumer which usually helps with designing cleaner API architecture
  • Faster development - as all boilerplate code is automatically generated you won't have to write it, all that's left is developing business logic.
  • Faster feedback loops - consumers can get a view of the API immediately and they can easier offer suggestions simply by modifying the spec

Let's develop our API in a spec-first approach!

6
10 3569
Question Eduard Lebedyuk · Nov 14, 2019

I have several Business Services which I need to run once on each trigger.

Trigger can be either:

  • Specific time (so once a day, every day)
  • Specific day (so once a month, every month)

For the time, it would be stable (i.e. 0100), but the second case varies - one month it could be 10th, another month - 12th.

After each run I want the service to turn off, so that all the time the service is not running it would be colored grey in Production Management Page.

I plan to use Task Scheduler,but open to suggestions.

Thoughts? Ideas? Code?

2
0 498
Announcement Eduard Lebedyuk · Nov 12, 2019

First webinar on  InterSystems API Management!


We are pleased to invite you to the upcoming webinar in Russian: Introduction to InterSystems API Management on November 21 at 10:00 Moscow time (GMT+3)!

As you might have heard, we recently introduced the InterSystems API Manager (IAM) - a new feature of the InterSystems IRIS Data Platform,
enabling you to monitor, control and govern traffic to and from web-based APIs within your IT infrastructure.

In this webinar I will highlight some of the many capabilities IAM allows you to leverage. InterSystems API Manager brings everything you need:

  • to monitor your HTTP-based API traffic and understand who is using your APIs; what are your most popular APIs and which could require a rework.
  • to control who is using your APIs and restrict usage in various ways. From simple access restrictions to throttling API traffic and fine-tuning request payloads, you have fine-grained control and can react quickly.
  • to protect your APIs with central security mechanisms like OAuth2.0 or Key Token Authentication.
  • to onboard third-party developers and provide them with a superb developer experience right from the start by providing a dedicated Developer Portal for their needs.
  • to scale your API demands and deliver low-latency responses

There would be a live demo.

This webinar is for System Architects, Developers and DevOps Engineers.
Time: November 21 at 10:00 Moscow time (GMT+3)!

The language of the webinar is Russian.


Register!

5
0 424
Article Eduard Lebedyuk · Oct 21, 2019 4m read

InterSystems API Management (IAM) - a new feature of the InterSystems IRIS Data Platform, enables you to monitor, control and govern traffic to and from web-based APIs within your IT infrastructure. In case you missed it, here is the link to the announcement. And here's an article explaining how to start working with IAM.

In this article, we would use InterSystems API Management to Load Balance an API.

In our case, we have 2 InterSystems IRIS instances with /api/atelier REST API that we want to publish for our clients.

There are many different reasons why we might want to do that, such as:

  • Load balancing to spread the workload across servers
  • Blue-green deployment: we have two servers, one "prod", other "dev" and we might want to switch between them
  • Canary deployment: we might publish the new version only on one server and move 1% of clients there
  • High availability configuration
  • etc.
3
4 1030
Question Eduard Lebedyuk · Oct 12, 2019

The question is pretty much in title. I'm developing a REST API, it has a search endpoint with 10 optional parameters. How do I pass them and stay RESTFul?

To ease the question a bit let's agree that:

  • all parameters are AND parameters, user can't make combos, ORs, etc. User can only provide values
  • all values are integers so I don't have to think about URL limits
  • all values are atomic
  • all conditions are about equivalency

Some options I know of:

1. URL parameters.

GET /search?param1=value1&param2=value2...

Quick and easy but I'm not sure it's really RESTFul

9
0 4595
Article Eduard Lebedyuk · Oct 10, 2019 7m read

This series of articles would cover Python Gateway for InterSystems Data Platforms. Execute Python code and more from InterSystems IRIS. This project brings you the power of Python right into your InterSystems IRIS environment:

  • Execute arbitrary Python code
  • Seamlessly transfer data from InterSystems IRIS into Python
  • Build intelligent Interoperability business processes with Python Interoperability Adapter
  • Save, examine, modify and restore Python context from InterSystems IRIS

Other articles

The plan for the series so far (subject to change).

0
1 777
Question Eduard Lebedyuk · Oct 1, 2019

I need to know the current rss memory consumption. On earlier Cache versions I used this method:

set sc = ##class(%Net.Remote.Utility).RunCommandViaZF("smem -u cacheusr | grep cacheusr | awk '{print $6}'",,.rss)

It doesn't work because we use $zf(-100) on IRIS 2019.1.

New version:

ClassMethod Test()
{
set cmd = "smem"
set args = 8
set args(1)="-u"
set args(2)="irisusr"
set args(3)="|"
set args(4)="grep"
set args(5)="irisusr"
set args(6)="|"
set args(7)="awk"
set args(8)="'{print $6}'"
set sc = ##class(%Net.Remote.Utility).RunCommandViaZF(cmd,,.rss,,,.code,.args)
//set sc = $zf(-100, "", cmd, .args)
zw rss,sc
}
2
0 464
Question Eduard Lebedyuk · Sep 14, 2019

What's the best way to replace character groups?

I want not to remove character groups as $zstrip does but to replace them with whitespaces.

$translate needs explicit character list.

Effectively I want to remove any characters besides letters, numbers and a small (known) subset of punctuation characters, replacing everything else with whitespaces.

6
0 819
Announcement Eduard Lebedyuk · Sep 12, 2019

I'm happy to announce the latest Python Gateway release.

This is not an InterSystems product, it is community supported open source project.

Download new release from GitHub.

Now for the new features.

Fast transfer. Pass globals, classes and tables from InterSystems IRIS to Python with ease and speed (10x faster than old QueryExecute). Documentation.

Proxy Gateway allows generation of ObjectScript classes for Python classes. Instantinate objects, call object and class methods using familiar ObjectScript code (docs).

set module = "random"
set sc = ##class(isc.py.gw.Generator).Generate(module)
set sc = ##class(isc.py.Main).ImportModule(module)
write ##class(py.random).randint(1,100)
8
0 599
Announcement Eduard Lebedyuk · Sep 10, 2019

Code golf is a type of recreational computer programming competition in which participants strive to achieve the shortest possible source code that implements a certain algorithm.

Here's a list of Code Golf competitions we had on Developers Community.

And some interesting challenges:

Did I miss something? Add more challenges in comments.

0
0 536
Article Eduard Lebedyuk · Sep 9, 2019 1m read

Just wanted to share my Zabbix template for monitoring InterSystems IRIS on Linux servers.

It monitors irisusr (configurable) memory consumption:

  • Virtual memory size
  • Percentage of real memory
  • Resident set size
  • Size of data segment
  • Size of code segment
  • Peak resident set size
  • Size of locked memory
  • Size of shared libraries
  • Peak virtual memory size
  • Size of pinned pages
  • Size of page table entries
  • Size of process code + data + stack segments
  • Size of stack segment
  • Size of swap space used

How to use:

  1. Check that you have Zabbix installed (I'm using version 4.
5
0 1645
Question Eduard Lebedyuk · Sep 8, 2019

Is there a way to set null in dynamic object without using %Set methods?

I have this method and I need to set NULL as, well, null and not string.

ClassMethod node(name) [ CodeMode = expression ]
{
{
    "name":(name),
    "content":($case(##class(%Dictionary.ClassDefinition).%ExistsId(name), $$$YES:"mycontent", $$$NO:"NULL"))
}
}
3
0 836
Question Eduard Lebedyuk · Sep 8, 2019

I'm writing "Finder"-like dialog and need to get list of BPL classes.

The query is dependent on current "path" - it outputs all BPLs in the current path (if any) and all sub-packages which contains BPLs.

So far I have this query:

Query getBPL(path, needPlus = {(path'="")}) As %SQLQuery
{
SELECT DISTINCT $PIECE(Name, '.', 1, $LENGTH(:path, '.') + :needPlus) Name
FROM %Dictionary.ClassDefinitionQuery_SubclassOf('Ens.BusinessProcessBPL')
WHERE Name %STARTSWITH :path
}

My problem is, if I'm not in "root" path I need to add additional dot level, but in root path I only need to add one.

2
0 539
Question Eduard Lebedyuk · Aug 17, 2019

 I have two local instances:

  • IRIS for Windows (x86-64) 2018.1.2 (Build 626_3U) Wed Jun 12 2019 19:07:59 EDT
  • IRIS for Windows (x86-64) 2019.1 (Build 510U) Thu Mar 14 2019 14:13:37 EDT

I'm using Java Gateway to talk to external system.

Both instances are using the same:

  • jar
  • generated class
  • java version


They are calling the same method with this java signature:

package isc.rabbitmq;
public class API {
    public void sendMessage(byte[] msg) throws Exception {}
}

On the InterSystems IRIS side I'm calling it like this:

set sc = ##class(%Net.Remote.Service).OpenGateway(gatewayName, .gatewayConfig)
set sc = ##class(%Net.Remote.Service).ConnectGateway(gatewayConfig, .gateway, "PATH-TO-JAR", 1)
set api = ##class(isc.rabbitmq.API).%New(gateway)
set stream = ##class(%GlobalBinaryStream).%New()
do stream.Write(123456)
d api.sendMessage(stream)
1
1 298
Discussion Eduard Lebedyuk · Jul 31, 2019

Let's have a round of CodeGolf!

As usual the goal is to write the shortest solution for a specified problem.

Today we have one of the classics: FizzBuzz.

Write a program that prints the numbers from 1 to 100.

But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”.

For numbers which are multiples of both three and five print “FizzBuzz”

22
1 821
Question Eduard Lebedyuk · Jul 23, 2019

I have this fact table

CheckTime Error Marker (1 or 0)
2019-01-01 00:01:00 1 0
2019-01-01 00:02:00 5 1
2019-01-01 00:03:00 2 0

And the cube which is pretty much 1:1.

I have build an MDX:

SELECT NON EMPTY [Measures].[Error] ON 0,NON EMPTY [CheckTime].[H1].[Minute].Members ON 1 FROM [CHECKCUBE]

Which produced this chart in DeepSeeWeb (there's obviously more data, but you get an idea):

However, I want to add a Marker - if it equals 1 then I need some indication on the chart, so the graph should look like this:

Is there a way to do that in DeepSee or DeepSeeWeb?

2
0 316
Article Eduard Lebedyuk · Jul 16, 2019 4m read

When I describe InterSystems IRIS to more technically-minded people, I always start with how it is a multimodel DBMS at its core.

In my opinion that is its main advantage (on the DBMS side). And the data is stored only once. You just choose the access API you want to use.

  • You want some sort of summary for your data? Use SQL!
  • Do you want to work extensively with one record? Use objects!
  • Want to access or set one value and you know the key? Use globals!
1
5 1704