Alexey Maslov · Sep 29, 2020 go to post

Evgeny,
Is it a question: try/catch (or another way of error handling) or %Status? If we try to follow some solid design principles, each method should perform only one function, have only one way to exit from, and should inform the caller whether it succeded. So, we should use both. Extending your sample: 

ClassMethod solid1(parameter, ...) as %Status
{
  set sc=$$$OK
  try {
     $$$TOE(sc,##class(x.y).a())
     $$$TOE(sc,##class(x.y).b())
     ...
     $$$TOE(sc,obj.NormalMethod(parameter))
     ...
  } catch e {
     // error handling
     set sc=e.AsStatus()
  }
  // finally... common finalization for both (good or bad) cases
  return sc
}

One could write it in another fashion, e.g.

ClassMethod solid2(parameter, ...) as %Status
{
  set sc=$$$OK
  new $estack,$etrap
  set $etrap="if $estack=0 goto errProc"
  set sc=##class(x.y).a()) if 'sc goto solid2Q
  set sc=##class(x.y).b()) if 'sc goto solid2Q
  ...
  set sc=obj.NormalMethod(parameter) if 'sc goto solid2Q
  ...
solid2Q
  // finally... common finalization for both (good or bad) cases
  return sc

errProc // common error handler
  // error handling
  set sc=$$$ERROR(5001,"solid2 failed: "_$ze)
  goto solid2Q
}

Which version is better? If we don't need individual error handling of ##class(x.y).a(), ##class(x.y).b(), etc calls, I'd prefer solid1. Otherwise, solid2 seems to be more flexible: it's easy to add some extra processing of each call return. To achieve the same flexibility in solid1, we are to cover each call in an individual try-catch pair, making the coding style too heavy.

Alexey Maslov · Sep 11, 2020 go to post

 ...as much as possible avoid the need to use subscript level mapping (SLM) to manage growth of a single global across multiple databases. 

Ray, may I ask you: why should we avoid it?

Alexey Maslov · Sep 11, 2020 go to post

Several ##class can be eliminated, making the code shorter and readable writable better:

ClassMethod CRUDUser(id, name) As %String{q:'$d(name) "Name required" s x=$classmethod("Data.User",$s($g(id)="":"%New",1:"%OpenId"),$g(id)) q:'x "User not found"
  s x.Name=name q $s(x.%Save()=1:"User saved",1:"Error saving")}
Alexey Maslov · Sep 4, 2020 go to post

Nigel,
I'm OK with the answers given by Eduard and Danny. After moving to VS Code situation with snippets would be even better.
Thank you again.

Alexey Maslov · Sep 4, 2020 go to post

Thank you, Nigel.

Multi-line macros don't meet my needs. What I really need are fillable patterns (templates), to prompt developers on writing methods (functions) descriptions in a standardized manner, something like this: 

/// --------------------------------------------------------------------------------------------/// Method purpose/// ///  **Arguments**////// #. *pArg1*:/// #. *pArg2*:/// ///  **Returns**/////////  **Notes**/// /// ///  **Call sample**/// ::/// ///   ; code line 1///   ; code line 2/// 
Alexey Maslov · Sep 2, 2020 go to post

Daniel,
Not talking about whether $zerror/$ztrap is good or bad, false positives and negatives can be avoided if use it right way. The well-known pattern is as follows:

rouA
  set $ze="",$zt="rouAerr"
  ...
  set sc=$$funB() if 'sc quit sc
  ...
  quit sc
rouAerr
  set $zt="" ; that's of great importance!
  set sc=$$$ERROR(5002,$ze) ; just a sample of processing $ze...
  quit sc

funB()
  set $ze="",$zt="funBerr" ; while not neccessary, local $ztrap can be defined
  ...
  quit sc
funBerr
  set $zt=""
  set sc=$$$ERROR(5002,$ze)
  quit sc
Alexey Maslov · Sep 2, 2020 go to post

I am not putting my hopes on GBLOCKCOPY  due to its limitations

This precaution sounds strange in your context: if you are simply copying a set of globals that are actively being modified, you will get an unpredictable result nevertheless the utility you choose. To make a consistent copy, one should apply journal records or (if copying to another Cache instance) use some cross-system technique, such as Mirroring or Shadowing, while both require Multi-Server cache.key.

If you tell us more about the task you are trying to solve, we'd advise you better.

Alexey Maslov · Jul 23, 2020 go to post

it is a part of admin-panel of our web-application

I guessed it was not ad hoc writing ;)

Even with some universal tool like your admin panel, you can generate only those tasks which code you preliminary prepared with code.Write() commands. The reasons of preparing code this way in this very case are still unclear for me: I can hardly imagine extra functionality you can add to the traditional approach demonstrated in Evgeny's reply.

Alexey Maslov · Jul 23, 2020 go to post

Alexandr,

why did you prefer generating the task class instead of just writing it in some text editor? Looks like overkill for such a small task.

Alexey Maslov · Jul 21, 2020 go to post

Yes, it's possible. You can use %SYS.Task for a Task API. Its methods and properties are well documented in its superclass %SYS.TaskSuper.

Alexey Maslov · Jun 16, 2020 go to post

Yone,

if you really moving the files every day, you don't need to check the date: there are no old files in your in-folders, because they have been deleted with mv  (move) command. Most pieces of software which does the similar tasks (e-mail clients and servers, SMS processors, etc) do it this way, moving files rather than just copying them. The simpler the better, isn't it? 

Alexey Maslov · Jun 15, 2020 go to post

Please look at
https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?APP=1&CLASSNAME=%25SYSTEM.License
query ConnectionAppList()

The data source is the license server. The license server maintains counts of ISC.Appname license sections but does not manage other application license sections. Usage of other license sections can be examined with the ApplicationUserList query which returns license use for all applications on the current Cache instance.

 "...other application license sections" is just our case, so ISC licence server can't help much.

Alexey Maslov · Jun 15, 2020 go to post

Eduard,

If you are still interested: Application licensing doesn't support distributed license accounting; it was the stopper for us as our largest customer is running Cache based application (SP.ARM's HIS qMS) in distributed environment.
 

Alexey Maslov · Jun 11, 2020 go to post

I'd like cm that stands for community. Everybody knows that we are all developers here, so this is not of great need to be reminded. Just IMHO :)

Alexey Maslov · Jun 11, 2020 go to post

Do you plan to allow subpackages, e.g. dc.myapp?
What to do with those apps that had been already uploaded to Open Exchange before this naming convention will be established?

Alexey Maslov · May 14, 2020 go to post

Hi James,

A colleague of mine developed JDBC based solution in question which works with Oracle, mySQL and Caché a while ago.
It's based on the following classes:

   %Net.Remote.Java.JavaGateway
   %Net.Remote.Java.JDBCGateway (This class is used internally by Caché. You should not make direct use of it within your applications.)

Despite the last remark, InterSystems follows the similar approach in its Ensemble / IRIS outbound adapters.
Our solution is compatible with actual versions of Caché and IRIS. Regretfully, it's too bound to our app, so I'm not sure whether it is the best source of sample code at the moment.
 

Alexey Maslov · May 8, 2020 go to post

It depends.

Switch 10 which inhibits all global/routine access except by the process that sets this switch should meet, while setting it can interfere with your _own_ activity.
Switch 12 which disables logins can be insufficient for disabling web access, which is easier to restrict by stopping web server.

I didn't personally experiment with those switches as we have no such problem because our application utilizes its own "disable logins" flag by locking the variable.

Alexey Maslov · May 7, 2020 go to post

to avoid unexpected problems with other user operations 

... is usually easier to disable users sign-on by setting switch 12, or restrict their activity by some other appropriate switches combination (see Using Switches).

Alexey Maslov · Apr 20, 2020 go to post

Another possible approach:

  • copy global stream to file
  • process it using external OS call; in Linux we use its native zip/unzip utilities, in Windows - console version of popular free 7-zip tool. 
Alexey Maslov · Apr 2, 2020 go to post

Hi Graham,
the code published above is a Task Manager task. If you need flexible Task to purge .cbk and .log files created by internal online backup tasks of any kind, you may also want to look at cmPurgeBackup.

Alexey Maslov · Mar 17, 2020 go to post

Just adding 2c to Kevin's reply.

Most hosts that support TCP also support TCP Keepalive  

Besides, server application should support it. 3 hours keepalivetime setting is not typical; it sounds like your server app not tuned for keepalive support or doesn't support it at all.

In case of IRIS/Caché, you should explicitly set some options on connected server socket, e.g.:

start(port)// start port listenerio="|TCP|"_portio:(:port:"APSTE"):20 e  quit  while 1 {io x   u $p// connection is accepted: fork child processchild:(:5:io:io)  }
 
child  use $p:(:/KEEPALIVE=60:/POLLDISCON)
  ...

/KEEPALIVE=60 to set keepalivetime to 60 seconds
/POLLDISCON to switch on TCP probes.

Alexey Maslov · Mar 10, 2020 go to post

Stuart,

Unless you publish the failing code fragment, it would be difficult to help you.

Alexey Maslov · Mar 2, 2020 go to post

Congrats!

Can we expect publishing your code aimed "...to simulate NYSE data processing (Order/Fill)..." as an Open Exchange App?
 

Alexey Maslov · Feb 27, 2020 go to post

Thanks, Alexander.

Do you know by chance, why RHEL 8 listed as a platform for IRIS 2019.1.1 was excluded from the list for (unreleased) IRIS 2019.1.4 and even for (pre-released) 2020.1?

Alexey Maslov · Feb 17, 2020 go to post

Paul's warning sounded like this setting changed after the instance re-installation, while it unlikely could, as even in IRIS, according to docs:

System-Wide Security Parameters
Allow multiple security domains ... [Default is a single domain]

Alexey Maslov · Feb 7, 2020 go to post

OK, but OP's intention was to

block analysts to start the interface in copy #2

while your method just checking whether it's free.