Dmitry Maslennikov · Oct 12, 2020 go to post

At the same time, I would not recommend spending time on official webgateway docker image, as it made to be too specific for ICM and/or Durable %SYS. And at the same time, needs some magic to get it working. e.g. apache will not start without specifically saying so. And even if it started, it does not mean, that it will be started with the CSP module enabled.

Dmitry Maslennikov · Oct 12, 2020 go to post

Instructions of what? If saying just about Apache+webgateway.

The repo I've provided is quite complete. With some basic knowledge of docker.

So, you just have to build the docker image, publish it to some docker registry, public or private and deploy it with AWS

Deploying just IRIS itself as a container does not make so much sense at all. As it needs to be packed with some application it should run. Containerized IRIS it's not the same as IRIS running on a virtual machine, it's very different, and not so easy to explain it in a simple way.

For instance, you can look at this article, about deploying some web-based IRIS application on Amazon

I would recommend, to contact me through info@caretdev.com, so, we could schedule a discussion, where you could give more details, and I will say the ways how it can be solved. 

Dmitry Maslennikov · Oct 12, 2020 go to post

Are two of these dates 202010011000 and 8/6/2018 9:10 PM equal?

Or, what the format for the numeric one?

Dmitry Maslennikov · Oct 10, 2020 go to post

Having separate Apache it's not something unordinary, and in fact, is just a recommended way for web-based applications.

And Apache in docker or not have no difference. The configuration will be exactly the same.

You can look at my example I made some time ago. It uses docker-compose, but the key feature, that it should use the same network, which creates by default in docker-compose configuration for the services in the same project. So, you just have to prepare apache with webgateway, and properly configured. Or like in my case, webgateway can be configured by environment variables, so, the same image can be used multiple times with different IRIS servers.

Look at my project, it implements a backend, where frontend can be any, In my example it uses Vue by default, and Angular and React as option. Frontend, is that something, that completely not related to InterSystems at all. You can do it in any way you like. In project RealWorld you can find lots of realizations of exactly the same frontend. And any of this realization can be used with any of realization of backend, and in our case, it can be IRIS as well. And this project is very cool in case, when you would like to see, how to do the same in a different way.

There is only one way to do it, is to use any supported webserver, Apache or Nginx, and do not use built-in apache. Configure the chosen server to work with InterSystems products. And configure SSL for that server, in any way by instructions you can find on the internet.

You can use property "links" in "objectscript.conn", to add some links to your projects, which you will be able to open quickly

  "objectscript.conn": {
    "active": true,
    "username": "_system",
    "password": "SYS",
    "ns": "MYAPP",
    "port": 52773,
    "links": {
      "MyApp": "http://${host}:${port}/csp/${namespace}/main.csp"
    }
  }

After this, you will get a new item in the menu shown by click on the status bar with connection info.

While you are working with JSON, I would recommend to not do it manually and use native JSON support, available since 2016.2 (2016.1 with notes).

So, you can do it just 

set json = {}.%FromJSON(str)

or

set json = {}.%FromJSON(stream)

and value will be available by

write json."Not  Working Example"

If you have a version with no native JSON support, look at this project

Dmitry Maslennikov · Sep 30, 2020 go to post

I don't see XML here, but for your examples, I would use Regex

    Set regex = ##class(%Regex.Matcher).%New("(""[^""]*""):\s(""[^""]*""|[^,]*)")     
    
    Set regex.Text = """Working Example"": xyz,"
    Write !,regex.Text,!
    If regex.Locate() {
      Write !?5,regex.Group(1)
      Write !?5,regex.Group(2)
    }
    Write !     
    
    Set regex.Text = """Not  Working Example"": ""x,  y"","
    Write !,regex.Text,!
    If regex.Locate() {
      Write !?5,regex.Group(1)
      Write !?5,regex.Group(2)
    }

And the output will be

"Working Example": xyz, 
     "Working Example"
     xyz

"Not  Working Example": "x,  y",
     "Not  Working Example"
     "x,  y"
Dmitry Maslennikov · Sep 25, 2020 go to post

project awesome, is completely different, it's not about snippets, it's about real projects, complete and awesome

so, I would name our project, just as simple, objectscript-snippets

Dmitry Maslennikov · Sep 25, 2020 go to post

By code sections, I would get some code snippets. In VSCode, you can easily add any amount of snippets, look at this article.

And VSCode will offer to insert code snippet, while you typing text written in prefix of the snippet.

Dmitry Maslennikov · Sep 23, 2020 go to post

There is no xsd. And much better would be to convert sources from xml to udl, and it’s possible to do it even with the history of changes. Our company can help with it, please contact us, info@caretdev.com

Dmitry Maslennikov · Sep 23, 2020 go to post

The only way to get it worked with CSP files right now, is to configure isfs. In this case, you will edit any files only remotely, with no local files.
You need file with code-workspace extension and content like this.

{
"folders": {
"uri": "isfs://yourserver/csp/user?ns=USER&csp"
}
}

More details, on how to configure and work with isfs, in the documentation

Dmitry Maslennikov · Sep 22, 2020 go to post

And just a note, for one more issue. The description to method %JSONNew says, that I can pass JSON which will be imported to the just created object

/// Get an instance of an JSON enabled class.<br><br>
/// 
/// You may override this method to do custom processing (such as initializing
/// the object instance) before returning an instance of this class.
/// However, this method should not be called directly from user code.<br>
/// Arguments:<br>
///     dynamicObject is the dynamic object with thee values to be assigned to the new object.<br>
///     containerOref is the containing object instance when called from JSONImport.
ClassMethod %JSONNew(dynamicObject As %DynamicObject, containerOref As %RegisteredObject = "") As %RegisteredObject [ CodeMode = generator, GenerateAfter = %JSONGenerate, ServerOnly = 1 ]
{
    Quit ##class(%JSON.Generator).JSONNew(.%mode,.%class,.%property,.%method,.%parameter,.%codemode,.%code,.%classmodify,.%context)
}

But in fact, it does does nothing with it, and generated code, just returns new object

%JSONNew(dynamicObject,containerOref="") public {
  Quit ##class(Conduit.Model.User).%New()
}
Dmitry Maslennikov · Sep 22, 2020 go to post

To be able to export %Id() as id property in JSON, I had to add this.

Property id As %Integer [ Calculated, SqlComputeCode = { Set {*} = {%%ID} }, SqlComputed ];

I think, that it would be better to have some parameter in a class which would enable to output id easier without hacks.

Dmitry Maslennikov · Sep 22, 2020 go to post

Yeah, I know that I can do %FromJSON, but it looks like overhead, here.

Look at this article, you can generate API implementation just from swagger specification. It generates a bunch of methods for each call in swagger spec.

Something like this

/// Get an article. Auth not required<br/>
/// The method arguments hold values for:<br/>
///     slug, Slug of the article to get<br/>
ClassMethod GetArticle(slug As %String) As %DynamicObject
{
    //(Place business logic here)
    //Do ..%SetStatusCode(<HTTP_status_code>)
    //Do ..%SetHeader(<name>,<value>)
    //Quit (Place response here) ; response may be a string, stream or dynamic object
}

So, in this method, I would add code like this

/// Get an article. Auth not required<br/>
/// The method arguments hold values for:<br/>
///     slug, Slug of the article to get<br/>
ClassMethod GetArticle(slug As %String) As %DynamicObject
{
    Set article = ##class(Article).slugOpen(slug,, .tSC)
    If $$$ISERR(tSC) {
        Do ..%SetStatusCode(404)
        Return 
    }
    
    Return article
    #; Or
    Return article.%JSONExport()
}

But this will not work. The only ways to make to work is to return string or stream

Return article.%JSONExportToString()
Return article.%JSONExportToStream()

But, I have to wrap the output. And the best would be to get something like this

Return { "article": (article.%JSONExport()) }

While I have to write this, and hope do not get MAXSTRING error, for some cases

Return "{ ""article"": " _ article.%JSONExportToString() _ "}"

And it's just only a case with one object, while for some cases I have to return an array.

Dmitry Maslennikov · Sep 18, 2020 go to post

Definitely, something wrong in the configuration. Code in InterSystems in fact is no different from any other data stored there. So, you may have some wrong mappings, or store some of your code in %SYS. 

I have a configuration with mirroring + ECP, and it works perfectly, I don't even care which of the nodes is primary, and can switch it any time, with no issues. And I have even more than one Code databases, and more than 20 Data databases. Mirroring Nodes works on 2018.1 while ECP Application Servers on 2012.2, with no issues.

If you have some doubts about your configuration, you can ask for help through WRC, or we can help you with it, we can review your settings, and say what actually happened and how to solve it

Dmitry Maslennikov · Sep 14, 2020 go to post

I would suggest a few points, how to catch what's going on wrong with the unexpected growth of databases, it's not actually really matter iristemp/cachetemp or some other.

  • zn "%SYS" Do ^GLOBUFF - will show you the biggest globals in the Global Buffer, useful tool to inspect slowness as well. If you see that some global from iristemp uses too much of global buffer, you can use it to investigate further
  • Integrity check for growing database, if the size not too big, it's the simplest way to understand the sizes of globals in the database.

When you found exact global name, you now have a point where to start an investigation.

If you stopped IRIS, you can just delete IRISTEMP, it will be recreated as a new in any way, after the start.

Dmitry Maslennikov · Sep 14, 2020 go to post

Sorry for that, could you please fill the issue here? This check needed to be sure, that file on the server has not been updated while edited in VSCode. And may not work perfectly, yet, unfortunately.

As a workaround, I would suggest using import right in Caché/IRIS with a common way through $system.OBJ.Load/ImportDir

It's In fact not a common task for an editor, to import big amounts of files. So, the best behavior you'll get if you compile it separately from the editor.

Dmitry Maslennikov · Sep 14, 2020 go to post

At the moment, you can only search by local files. Search by files stored on the server on the way. You can look for the details here.

Dmitry Maslennikov · Sep 11, 2020 go to post

I have not been worked with Visual Studio, so, have no idea how it works there. But Instead of Studio, I would recommend using VSCode, of course, it already supports debugging, for sure you can watch variables (and expressions) as well as hovering variables. It does not support objects in a some readable way but supports it as an expression, so obj.property will work.

Dmitry Maslennikov · Sep 11, 2020 go to post

Unfortunately, for some reasons some systems may not use the latest versions of InterSystems products. While Integrity checks in some cases can be used on lower versions. And from the other side, for some systems reversing the system to some backup can be used as only last chance to restore the data, due to the sensitivity of stored data and the impossibility to restore data since the latest backup. So, If I would find database degradation I would better attempt to recover it, fortunately, I have an experience, and possibly lose some data, but the amount of lost data will be significantly less then when I would use a backup. Around 100 hundred GB journals per day, with tens of terabytes of data supposed for backup, make the task to restore system quickly as impossible for a system that has to be available with no downtime.