Miserver - User as a session

MiServer is Dyalog's APL-based web development framework

Miserver - User as a session

Postby Gantois on Tue Apr 12, 2016 12:43 pm

Hi,
I'm using Miserver ("user" as a session). There are some component files with one administration class for each. At the beginning of dyalog functions I put instructions as following (some of them calling the same file class). In that case, when I change page (navigation menu for example) The same file is referencied again with diferent tie number. Is that a problem?

The system is running without problem or error (I'm testing on local host), but I think it is not the right way. Can I open/referencied the files only one time for each logged user? Could anyone show me the right way?

Example 1: FunctionX.dyalog:
:Field Public inicialized←0
:If ~inicialized
AA←⎕NEW #.fileA 'filenameA'
BB←⎕NEW #.fileB ('filenameB' 'userid')
inicialized←1
:EndIf

Example 2: FunctionY.dyalog:
:Field Public inicialized←0
:If ~inicialized
AA←⎕NEW #.fileA 'filenameA'
BB←⎕NEW #.fileB ('filenameB ' 'userid')
CC←⎕NEW #.fileC 'filenameC '
inicialized←1
:EndIf

On that example the file "filenameA" is referencied with diferent ties.

Thanks,
Marco
Gantois
 
Posts: 80
Joined: Thu Apr 17, 2014 9:44 am

Re: Miserver - User as a session

Postby MBaas on Tue Apr 12, 2016 2:12 pm

Hi Marco,

I must admit I did not fully understand the details of your msg. However, the way I would do it, is to define my own server-class (put a MarcoServer.dyalog in the code-directory of your app, and in it define as follows:

Code: Select all
:class MarcoServer :MiServer

∇ onSessionStart req
:access public override
⍝ read files specific to user session, place content in req.Session


:endclass

Then do all this user-specific initialisation stuff there: read required files and store the data in the Session (Session is a namespace which may hold any data that is specific to this session...)
Last edited by MBaas on Wed Apr 13, 2016 1:50 pm, edited 1 time in total.
User avatar
MBaas
 
Posts: 156
Joined: Thu Oct 16, 2008 1:17 am
Location: Gründau / Germany

Re: Miserver - User as a session

Postby Morten|Dyalog on Wed Apr 13, 2016 7:26 am

Gantois wrote:Can I open/reference the files only one time for each logged user?

MiServer will create an instance of the page class for each simultaneous user, and your functions will run inside these instances. Dyalog APL allows a session to tie the same file more than once with diferent tie numbers, so your code will work as long as you are only reading the files.

However, beware: two (or more) calls may run in parallel on different threads, if your users are active simultaneously. You can not use ⎕FHOLD to separate these users, since they are both in the same process. So if UserA does a ⎕FHOLD and UserB does another one a moment later, UserA's hold will just be released.

There are several possible solutions... In increasing order of complexity:

  • Use a function with "critical sections" implemented using :Hold, that all users will share, and have it do the updates.
  • Run Slave processes to encapsulate each user in a separate process - we have some sample code for this that we can share.
  • Use the Dyalog File Server, which allows a single APL process to have multiple completely independent connections to the file server (this also requires a separate licence for the DFS, and is probably overkill for you at this point).
User avatar
Morten|Dyalog
 
Posts: 406
Joined: Tue Sep 09, 2008 3:52 pm

Re: Miserver - User as a session

Postby Gantois on Wed Apr 13, 2016 1:12 pm

MBaas and Morten,

Thanks for your prompt reply and clarification. MBaas, Where can I read about onSessionStart and its content?

Morten,
This is the heart of the matter. My system has some files for read (it is not a problem) but I have one file with several components to each diferent user . The first component of this file is a index (nested vector) identifying the numbers of each user's components. In that case there are independent data components for user, but it is necessary a hold control because the index component.

I understood in your explanation that I was making a mistake using []FHOLD inside my updates functions, since when my users are active simultaneously, they are both in the same process.

I will try to solve this problem using your first solution: a function with "critical sections" implemented using Hold, that all users will share, and have it do the updates.

It is my first website and, as you see, I have some conceptual doubts. I don't understand when you say "a function using hold that all users will share". I think that this control will be "outside of the same process", isn't it? If so, I don't know how to do this. Do you have a sample or a material that can I read/study?

Thanks,
Marco
Gantois
 
Posts: 80
Joined: Thu Apr 17, 2014 9:44 am

Re: Miserver - User as a session

Postby MBaas on Wed Apr 13, 2016 1:50 pm

Marco,

I think the best place to read about onSessionStart is the source-code or here - I don't think much has been written yet (but I haven't checked, so I might be wrong). But I also think there's not much that could be written: it is a function that you can provide in the Server-Class (aaaah, now that reminds me that I should have mentioned that you also need to "activate" that class by changing {AppDir}\Config\server.xml and inserting a tag "<server>" that specifies the name of the server - so in our example you need the following line
Code: Select all
<ClassName>MarcoServer</ClassName>

somewhere in server.xml. The onSessionStart-Function will (if it exists in the Server-Class) then be called whenever a new Session has been created. The "content" of onSessionStart might be any session-initalisation you need, for example: reading user-specific files etc. - so it depends entirely on you and your app what you do...
User avatar
MBaas
 
Posts: 156
Joined: Thu Oct 16, 2008 1:17 am
Location: Gründau / Germany

Re: Miserver - User as a session

Postby Morten|Dyalog on Wed Apr 13, 2016 2:04 pm

Sorry, the "that all users will share" is superfluous. You just need your updates to go via a block of code that is surrounded by a :Hold 'myfile' ... :EndHold, where 'myfile' is any array that uniquely identifies the resource, rather than ⎕FHOLD tn ... ⎕FHOLD ⍬. Since all users execute inside the same process, the :Holds will only allow one thread at a time to enter the code block.
User avatar
Morten|Dyalog
 
Posts: 406
Joined: Tue Sep 09, 2008 3:52 pm

Re: Miserver - User as a session

Postby Brian|Dyalog on Wed Apr 13, 2016 4:30 pm

Hi Marco!

Michael has the right idea. The best way to do this is to create your own class based on the MiServer class and then override the onSessionStart method.

The MiServer class has a number of methods that you can override in your own class (derived from MiServer).
Currently these are (you can find them in the "Override" section of the MiServer source code (see below).

Among the documents I'm working on is "Customizing MiServer" which will (hopefully) describe this and other techniques for tuning MiServer to your needs.

So, the steps you need to take are:
  • Create (or update) the Server.xml file in the /Config folder of your MiSite to have a <ClassName> entry with the name of your class (Micheal used 'MarcoServer' in his example)
    Do not update the files in the MiServer /Config folder. If you do, the next time you update MiServer from the GitHub repository, you'll have conflicts to resolve.

  • Write the derived class and the onSessionStart method.
    Make sure the class is derived from the MiServer class.
    Make sure the method is :Access Public Override

Overridable Server Methods in MiServer
      :section Override
⍝ ↓↓↓--- Methods which are usually overridden ---

∇ onServerLoad
:Access Public Overridable
⍝ Handle any server initialization prior to starting


∇ onServerStart
:Access Public Overridable
⍝ Handle any server startup processing


∇ onSessionStart req
:Access Public Overridable
⍝ Process a new session


∇ onSessionEnd session
:Access Public Overridable
⍝ Handle the end of a session


∇ onHandleRequest req
:Access Public Overridable
⍝ Called whenever a new request comes in


∇ onHandleMSP req
:Access Public Overridable
⍝ Called when MiPage invoked


∇ onIdle
:Access Public Overridable
⍝ Idle time handler - called when the server has gone idle for a period of time


∇ Error req
:Access Public Overridable
⍝ Handle trapped errors
req.Response.HTML←'<font face="APL385 Unicode" color="red">',(⊃,/⎕DM,¨⊂'<br/>'),'</font>'
req.Fail 500 ⍝ Internal Server Error
1 Log ⎕DM


∇ level Log msg
:Access Public overridable
⍝ Logs server messages
⍝ levels implemented in MildServer are:
⍝ 1-error/important, 2-warning, 4-informational, 8-transaction (GET/POST)
:If Config.LogMessageLevel bit level ⍝ if set to display this level of message
⎕←msg ⍝ display it
:EndIf


∇ Cleanup
:Access Public overridable
⍝ Perform any site specific cleanup


⍝ ↑↑↑--- End of Overridable methods ---
:endsection




I hope this helps!
/Brian
User avatar
Brian|Dyalog
 
Posts: 109
Joined: Thu Nov 26, 2009 4:02 pm
Location: West Henrietta, NY

Re: Miserver - User as a session

Postby Gantois on Mon Apr 18, 2016 8:40 am

Hi Michael, Morten an Brian,

Thanks very much for your explanation. I´m sure that will be essential for continuit of my system. I will test and apply them.

Marco
Gantois
 
Posts: 80
Joined: Thu Apr 17, 2014 9:44 am


Return to MiServer

Who is online

Users browsing this forum: No registered users and 1 guest