Eduard Lebedyuk · Feb 1, 2018 go to post

You can use this SQL directly:

SELECT COUNT(1)
FROM Your.Table

Or if you want to pass class name as an argument, you can wrap it in SQL procedure:

Class Utils.Dictionary
{

/// Call from SQL: SELECT Utils.Dictionary_GetExtentSize('Utils.Persistent') As ExtentSize
/// write ##class(Utils.Dictionary).GetExtentSize("Utils.Persistent")
ClassMethod GetExtentSize(class) As %Integer [ SqlProc ]
{
  /// Convert class name to table name.
  /// You can skip this step if you have table name already
  #define ClassSQLTable(%c) ($$$comClassKeyGet(%c,$$$cCLASSsqlschemaname)_"."_$$$comClassKeyGet(%c,$$$cCLASSsqltablename))
  set table = $$$ClassSQLTable(class)

  /// Quoter2 is called to escape table name if required
  set table = ##class(%CSP.UI.Portal.SQL.Home).Quoter2(table)

  /// Execute dynamic SQL
  /// Really %sqlcq.<NAMESPACE>.cls<NUMBER>
  #dim rs As %SQL.ISelectResult
  set rs = ##class(%SQL.Statement).%ExecDirect(,"SELECT COUNT(1) AS extentSize FROM " _ table)

  /// Get first result
  do rs.%Next()
  set extentSize = rs.extentSize

  quit extentSize
}

}

And call like this:

SELECT Utils.Dictionary_GetExtentSize('Utils.Persistent') As ExtentSize
Eduard Lebedyuk · Jan 31, 2018 go to post

Okay, what does GUID means in your case? I get how people have GUIDs and holidays have GUIDs, but the purpose for the GUID of a person+holiday combo escapes me.

Eduard Lebedyuk · Jan 31, 2018 go to post

Can you elaborate on your data model? What are your two tables, and what information joining them  generates.

Consider the following database: it has clients and products -and each client and each product has a guid.

The join between clients and products would mean semantically - what client bought which products.

But it's probably be better to store this information in another table - orders and just add properties/fk/relationships to clients and products.

You want GUIDs - a mark of persistency,  but you want them in a transient query. I think it would be better to create another table and populate it with the relevant data and new  GUIDs and return that new GUIDs.

Another approach would be exposing hash function as an sql procedure and passing both GUIDs into it and returning a hash to a client.

Eduard Lebedyuk · Jan 31, 2018 go to post

Post your isc.REST code.

Your web app config looks ok, but you need to check that:

  • UnknowUser is enabled
  • UnknownUser can access USER namespace (if it's a dev box just give him %ALL role)
  • License consumption is not 100%
Eduard Lebedyuk · Jan 30, 2018 go to post

This is not what the customer wants. He have a use case where he only needs to be able to create and decompress raw DEFLATE-compressed content.

What's the use case?

 

Also, why use node instead of just calling zlib directly:

zlib deflate string ?level?

I'm not talking about callout here (which could also be another valid approach) but just direct $zf(-1, "zlib ...") call

Eduard Lebedyuk · Jan 30, 2018 go to post

Can you please provide example of OnValidate?

Here's what I tried and it does not work:

Class Test.InboundAdapter Extends Ens.InboundAdapter
{

/// Stream class to store message body. Leave empty to use strings.
Property BodyClass As %Dictionary.CacheClassname;

Parameter SETTINGS = "BodyClass:Basic";

/// Does not get called.
Method OnValidate(args...)
{
    merge ^b = args
    quit $$$ERROR($$$GeneralError, "Some error")
}

/// Runtime only. And $username is always _Ensemble. ##super() is in Ens.Settings
Method AssignOneSetting(pProperty As %String, pValue As %String, pName As %String) As %Status
{
    set ^c($i(^c)) = $lb(pProperty, pValue, pName, $username)
    quit ##super(pProperty, pValue, pName)
}
}
Eduard Lebedyuk · Jan 29, 2018 go to post

You can give user %EnsRole_Operator role:
Role for operation staff managing the day-to-day status of a particular production. Users assigned to this role have the Read permission on the current configuration to determine what settings and code are in effect, but do not have permissions to modify the configuration. Operations staff may start and stop interfaces, and may start and stop the production. They do not have access to the contents of messages, but may resend messages which cause issues. Operators may view queue and job information, and may inspect the settings for purges, alerts, credentials, and lookup tables.

Other approach would be readonly access the tables of the Ens.Config package.

Eduard Lebedyuk · Jan 29, 2018 go to post

enable/diasable ( readonly ) the controllers such as ipaddress  and port

Can you elaborate on that? What do you want to do?

Eduard Lebedyuk · Jan 27, 2018 go to post

slash macro:

#if $$$isWINDOWS
///
    #define slash "\"
#else
///
    #define slash "/"
#endIf

That said, consider using %File API  to work with file names. I usually extract "storage directory" as an application-wide setting (normalized and validated on change) and just add a file name. This way user code can ignore most OS path differences.

Eduard Lebedyuk · Jan 25, 2018 go to post

There are some utilities for work with images. For example QR code generation via %SYS.QRCode.  There is also this Captcha generation project.

That said, imagemagick is doubtlessly the best solution.

Eduard Lebedyuk · Jan 25, 2018 go to post

SQL way (query docs, 1 means BS):

SELECT *
FROM Ens_Config.Production_EnumerateConfigItems('Your.Production', 1)

Object way:

set rs = ##class(Ens.Config.Production).EnumerateConfigItemsFunc("Your.Production", 1)
do rs.%Display()

Constants for Business Host Type (defined in EnsConstants.inc):

#define eHostTypeUnknown   0
#define eHostTypeService   1
#define eHostTypeProcess   2
#define eHostTypeOperation 3
#define eHostTypeActor     4
Eduard Lebedyuk · Jan 25, 2018 go to post

You can use Ens.Response class for an empty response and you need to init it:

Method OnMessage(request As Ens.StreamContainer, Output response As Ens.Response) As %Status
{
    set response = ##class(Ens.Response).%New()
    quit $$$OK
}

If you only want to see streams why not use <trace> in BP?

Eduard Lebedyuk · Jan 24, 2018 go to post

Postconditionals are to be used only for the most simple checks, for example:

set:a="" a=10

instead of

if a="" {
  set a=10
}

But several conditions (or several lines inside) should be as if, I agree.

Eduard Lebedyuk · Jan 24, 2018 go to post

For one-line if I prefer postconditionals:

set:a b=a

 

As for For - the option with braces. It's more readable. And one line inside For loop quickly and often becomes several lines, so braces become mandatory anyway.

Eduard Lebedyuk · Jan 24, 2018 go to post

Why do you need to check it at runtime? If source and target are from different but related  classes you can copy by their common ancestor (or by specified ancestor class). Or do you copy properties between two unrelated classes?

Eduard Lebedyuk · Jan 24, 2018 go to post

Nice example of using method generators.

Why do you need ExistsProperty? Here's a check I usually employ for class properties in generators:

 if prop.Internal || prop.Calculated || prop.ReadOnly || prop.Private || prop.Identity || prop.MultiDimensional  CONTINUE

It filters out all systems properties like Concurrency, %%OID and so on.

Eduard Lebedyuk · Jan 23, 2018 go to post

When talking about speed, one of the most important questions is what exactly do you need to speed up? You need to determine:

  • what queries are the most popular
  • what queries take the most time

to fix it. Some ways to fix performance are (easy to hard):

  • Add indices
  • Change classes
  • Change application architecture

Because in your case I see at least two request types which require different actions to speed them up:

  • Get last X changes
  • Get last X modified subjects
Eduard Lebedyuk · Jan 22, 2018 go to post

Header itself is another layer because it's meta information for the BPL state machine, which you're inside of. So I don't see how you can get header Id from inside the state machine without violating abstractions in place.

Still, %Context, %Process and %LastError are documented and acceptable to use.

Eduard Lebedyuk · Jan 22, 2018 go to post

You can access %Ensemble("%Process") as ..%Process so:

..%Process.%PrimaryRequestHeader.%Id()
Eduard Lebedyuk · Jan 19, 2018 go to post

Why would you want to do that?

Here's sample production class:

Class Test.Production Extends Ens.Production
{

XData ProductionDefinition
{
<Production Name="Test.Production" TestingEnabled="true" LogGeneralTraceEvents="true">
  <Description></Description>
  <ActorPoolSize>1</ActorPoolSize>
ion>
}

}

Ens.Config.Production serialized is XData ProductionDefinition and not the class itself.

To create production class automatically you need to:

  1. Create %Dictionary.ClassDefinition object for your test production
  2. Create Ens.Config.Production object
  3. Create %Dictionary.XDataDefinition
  4. Serialize (2) into (3)
  5. Insert XData (3) into (1)
  6. Save and compile (1)