Eduard Lebedyuk · Mar 30, 2019 go to post

It's actually a wrapper for the same idea - if HeadOfQueue is checked, the resend message is inserted with a higher priority than the highest priority existing queue message. It can be seen in EnQueue method of Ens.Queue class.

Eduard Lebedyuk · Mar 29, 2019 go to post

Mimedata is subscripted by name and index.

So in your case:

set name = "BulkFileUpload"
for i=1:1:%request.CountMimeData(name)
    set mimeData = %request.GetMimeData(name, , i)
}

On each iteration mimeData variable would hold the stream with one next mimedata.

%request is simply an object of %CSP.Request class, check the docs or code to know how it works.

Additionally you can use this snippet to see what's inside %request, %response and %session objects:

set %response.ContentType = "html"
do ##class(%CSP.Utils).DisplayAllObjects()
quit $$$OK
Eduard Lebedyuk · Mar 29, 2019 go to post

<FILEFULL>  - Caché attempted to allocate a disk block for more global data or routine storage, but the attempt failed because the Caché database is full and could not be expanded.

Affected db is /hs-connect-hom/db/BPINTEGRADEV-GLB.

Eduard Lebedyuk · Mar 28, 2019 go to post

Bitmap indices maintain one node per each chunk of 64 000 id's, if at least one id from that range exists. So random integer ids can slow bitmaps down. On the other hand if there are two consecutive but spread (i.e 1..1000 and 100000...110000) id sequences it would generate just 2 global nodes so everything should be ok in that scenario.

Check index global in various scenarios:

 

Example.Bitmap

Eduard Lebedyuk · Mar 28, 2019 go to post

Eduard, are you referring to the Priority property of the Ens.MessageHeader class?

Yes.

That seems to be used exclusively for marking the message for Async vs. Synchronous delivery.

These priorities are available:

#define eMessagePriorityHighSync 1
#define eMessagePrioritySync     2
#define eMessagePrioritySimSync  4
#define eMessagePriorityAsync    6

Sync by default is 2, so specifying priority 1 may indeed help. Cursory glance at Ens.Queue indicates that messages with priority 1 would be processed first.

Eduard Lebedyuk · Mar 28, 2019 go to post

While messages do have priority, it seems to be internal property. You can try to check it on a dev system but I'd advise against changing it on a production system.

The easiest way is to have two operations - one for priority source, another for everything else and route messages to one or another operation.

Eduard Lebedyuk · Mar 27, 2019 go to post

But this also means that you can't ship the whole vendor copy of the global as you will overwrite the onsite ID counter node.

You can! When you load globals specify /mergeglobal flag to merge the global with existing data instead of overwriting it:

set sc = $system.OBJ.Load("global.xml", "/mergeglobal=1")

seed the ID counter at the site to a really high number

Bitmap indices would really slow down from that.

Eduard Lebedyuk · Mar 27, 2019 go to post

$zf(-100) has different signature:

set cmd = """C:\Program Files (x86)\WinRAR\Rar.exe"""
set args(1) = "x"
set args(2) = path _ "*.dbf"
set args(3) = pathToExt
set sc = $ZF(-100,"/SHELL", cmd,.args)
Eduard Lebedyuk · Mar 26, 2019 go to post

If you're on pre 2019.1 you can use %ZEN.Auxiliary.jsonProvider and %ZEN.Auxiliary.altJSONProvider to convert arbitrary object to and from JSON.

If you're on 2019.1 you can use %JSON.Adaptor class which is similar to %XML.Adaptor.

Eduard Lebedyuk · Mar 26, 2019 go to post

Error shows that it's access/user error:

ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT

    1808 (0x710)

    The account used is a computer account. Use your global user account or local user account to access this server.

Eduard Lebedyuk · Mar 26, 2019 go to post

Cache runs as a service under SYSTEM account.

Check that this user has access to a network drive.

Eduard Lebedyuk · Mar 26, 2019 go to post

This applies to properties of a class correct? Not just methods?

Correct.

You have several solutions:

  1. Application level control. You have one table Term { Name, Type} and on the application level you decide for edits to go or not based on type. It is the fastest solution, but you need to write a application code and remember to check for type.
  2. Class-level control as described by you.
  3. Row-level security. Control access row by row.
Eduard Lebedyuk · Mar 25, 2019 go to post

The easiest way is to use JSON_OBJECT for everything. Fastest would be just writing to device from resultset. Combine these approaches to get the performance you need (add this code to Parent class and call Test method):


Query Display() As %SQLQuery
{
SELECT
    JSON_OBJECT(
        'ID':%ID,
        'Name': Name,
        'Description': Description,
        'Children':    Example.Parent_GetChildrenInfo(%ID)
    )
FROM Example.Parent
}

/// do ##class(Example.Parent).Test()
ClassMethod Test(count = 0)
{
    if count>0 {
        do ##class(Example.Child).%KillExtent()
        do ..%KillExtent()
        
        
        do ##class(Example.Child).Populate(count,,,,$$$NO)
        do ..Populate(count,,,,$$$NO)
    }
    
    do ..DisplayFunc().%Display()
}

ClassMethod GetChildrenInfo(id) As %String [ SqlProc ]
{
    #define CRLF                             $c(13,10)
    #define ZENJSISNUM(%val)                ($IsValidNum(%val)&&(%val=+(%val)))
    #define ZENJSNUM(%num)                    $fnumber(%num,"LON")
    #; JSON utility macros that use the JSON translation table instead of the JS translation table
    #define ZENJSTABLE(%format)                ("JS"_$S(%format["u":"ML",1:""))
    #define ZENJSONTABLE(%format)            ("JSON"_$S((%format["u"):"ML",1:""))
    #define ZENJSONESCAPE(%str,%format)        $S(%format["s":$ZCVT(%str,"O",$$$ZENJSONTABLE(%format)),1:$Replace($ZCVT(%str,"O",$$$ZENJSTABLE(%format)),"\'","'"))
    #define ZENJSONSTR(%str,%format)        (""""_$$$ZENJSONESCAPE(%str,%format)_"""")
    #define ZENJSONPROP(%prop,%format)        $$$ZENJSONSTR(%prop,%format)
    #define ZENJSONVALUE(%val,%format)        $S($$$ZENJSISNUM(%val):$$$ZENJSNUM(%val),$C(0)=(%val)||$ListValid(%val):"""""",1:$$$ZENJSONSTR(%val,%format))
    #define ZENJSONPAIR(%pr,%val,%format)    $$$ZENJSONPROP(%pr,%format)_":"_$$$ZENJSONVALUE(%val,%format)
    
    set out = "["   
    
    
    set ids = ..ChildrenGetStored(id)
    set ptr=0
    set separator=0
    while $listnext(ids,ptr,value) {
        set value = $lg(value)
        set:separator out = out _ ","

        set out = out _  "{"
        set out = out _  $$$ZENJSONPAIR("Name",##class(Example.Child).NameGetStored(value),"") _","
        set out = out _  $$$ZENJSONPAIR("Description",##class(Example.Child).DescriptionGetStored(value),"")
        set out = out _  "}"
        set separator = 1
    }
    
    set out = out _  "]"
    
    quit out
}
Eduard Lebedyuk · Mar 21, 2019 go to post

I once separated one Ensemble database (with code and data) into two databases (one db for code, one db for data) on a running system.

It was not difficult actually:

  1. Exported code from one database
  2. Created new database.
  3. Imported code into new database.
  4. In a namespace switched code database from old database to a newly created one.
  5. Deleted classes from old database.

But in my situation the code itself didn't change.

Eduard Lebedyuk · Mar 20, 2019 go to post

Another check. Properties can't be SQL reserved words. I often name properties "Date", etc. only to forget that they can't be used in SQL as is only quoted, so I need to go to Class view and rename them to something else.

Eduard Lebedyuk · Mar 20, 2019 go to post

The main check we need is parametrization. SQL should not be concattenated from user input, but user input should be passed as an argument.

Eduard Lebedyuk · Mar 20, 2019 go to post

Well, what do you want to do with that list? Depending on your use case, the solution may differ.

For example to get a list of dashboards execute this query:

SELECT *
FROM %DeepSee_Dashboard.Definition

And to get a list of Pivots execute this one:

SELECT *
FROM %DeepSee_Dashboard.Pivot

And in MDX2JSON project I need to get a list of dashboards visible to the current user.  I use custom result set for that (because user may have access to dashes but not to SQL).