I think this should work if your namespace is enabled for Ensemble / Interoperability

Check this in SMP:
SELECT count(IDFROM Ens.MessageHeader

ClassMethod FetchMsgCount() As %Integer [ PublicList = msgCount,SQLCODE ] 
{
    set msgCount=-1
&sql(SELECT count(IDINTO :msgCount FROM Ens.MessageHeader)
If SQLCODE=0 Quit msgCount
Quit SQLCODE
}

or just simpler


ClassMethod FetchMsgCount() As %Integer  [ ProcedureBlock = 0 ]
{
    set msgCount=-1
&sql(SELECT count(IDINTO :msgCount FROM Ens.MessageHeader)
If SQLCODE=0 Quit msgCount
Quit SQLCODE
}
 

Your last finding signals to me that you get blocked by [ProcedureBlock]

either try using %suspendedCount instead of suspendedCount

Method OnTask() As %Status [ PublicList = suspendedCount,SQLCODE ] 
{    //implementation }

or put it into a PublicList together with SQLCODE

https://docs.intersystems.com/iris20211/csp/docbook/DocBook.UI.Page.cls?KEY=ROBJ_method_publiclist
 

The license-mechanic is a little bit complicated:

  • users are identified by  username@127.0.0.1  (as mentioned already)
  • every new process consumes a license slot over its lifetime
  • each user gets a set of license slots  (typically 25)
  • once this limit (25) is exceeded ALL 25 slots are converted to normal (non-licenses)

As a consequence, a request for license number 26 consumes 25 additional licenses for that user !!
And these licenses come back to in the license slot mode only if ALL processes of that user are terminated
So using a single user (e.g. from CSP) is rather risky in that relation

$system.License.Login()  may help you cross that limit.
from docs:

This function will relinquish a license if the session/process is already holding
one under a different identifier and it will obtain a new one on the behalf of the
user ID provided.

If the MAXCONNECTIONS connection limit per user is exceeded,
the usual transition to one-license-unit-per-connection
will apply to this user identifier.
   

@Marlin Mixon 
 It is just not possible the way you tried. Because: (from class docs)

Move to this position in the stream. If this suceeds then return true, else return false. Note this implementation is not efficient because it searches from the start of the stream,

This means it does a Rewind() and a Read(position) 

• method Write(data As %RawString) as %Status

Appends the string data to the stream and advances the current stream position by the number of characters in data.

Note that a write operation immediately following a read or rewind will clear out the existing data in the stream.

%SYS>d ^SECURITY
  
1) User setup
2) Role setup
3) Service setup
4) Resource setup
5) Application setup
6) Auditing setup
8) SSL configuration setup
9) Mobile phone service provider setup
10) OpenAM Identity Services setup
11) Encryption key setup
12) System parameter setup
13) X509 User setup
14) KMIP server setup
15) Exit
 
Option? 1
 
1) Create user
2) Edit user
3) List users
4) Detailed list users
5) Delete user
6) Export users
7) Import users
8) Exit
 
Option?

so you can call the local  commandline ( session  or terminal) and run
your SELECT in SQL shell [  do $system.SQL.Shell() ]
or from SMP System->Explorer->SQL  to see if there is any content.

If there is some content you may try next to use variables from the global scope
for your  embeded SQL
instead of 
&sql(Select demoVersion into :DemoVersion from demointerface.DemoInstances where ID=:demoID)

try it with
&sql(Select demoVersion into :%DemoVersion from demointerface.DemoInstances where ID=:%demoID)

The VIEW as such could be understood as a complex SELECT which definition is stored in the system 
At the first time processing, all code for access is generated and cached in the system
and marked with a signature. this may take a few seconds.
In parallel, a significant amount of structural data are also cached

The next time you call it, the signature is calculated and the already cached code is executed. 
You save time for code generation and compilation.
If this happens shortly after the first call you take additional advantage of the cached structural data.
How much and how long structural data are caches depends on the available buffer pool

Hi @Jack Huser,
I assume you would agree it is fair to compare apples to apples
but not horse coaches to formula-1 cars.


Being proud that I never lost a benchmark by speed I rewrote your code
that is nice to read and maintain but not very efficient, going for something
more speedy to show the limits and then checked it against your class.
My test file has only 47MB containing 181566 lines.

DEMO>write ##class(JUH.Test).ReadFile(file)
execution: 214.931024
1
DEMO>write ##class(JUH.Test).ReadQuick(file)
execution: .753696
lines: 181566
1
DEMO>write .753696/214.931024*100_" %"
.3506687801385062028 %

I think 0.35% is quite an eye catcher.

And his is the class:

 ClassMethod ReadQuick(strINReadFile As %String = "") As %Status
 {
  open strINReadFile::1 
  else  write "Missing File",! quit '$$$OK 
  set eof=##class(%SYSTEM.Process).SetZEOF(1)
  use strINReadFile
  set time1=$zh 
  for line=0:1 {
    read strBuffer if $zeof set diff=$zh-time1 quit
    // do something with strBuffer
  }
  close strINReadFile
  do ##class(%SYSTEM.Process).SetZEOF(eof)
  write !,"execution: "_diff,!,"lines: ",line,!
  quit $$$OK
 }

I just couldn't resist my nature.