Log in

Advanced MDrivenServer periodic server-side actions

From MDrivenWiki

A re-occurring pattern when building multi user software systems is the need to execute periodic actions. With MDrivenServer you can use it to execute re-occurring actions, or periodic actions.

A Periodic action is defined by a selection expression that selects what objects to act on. For each object selected for a periodic action we want to do the “action” and that probably needs a cluster of objects and it needs to do different stuff to evolve some object state. To enable efficient load for such an object cluster you must define and associate a viewmodel with each periodic action.

The periodic action logic will load the viewmodel for your object and loop through all actions that it finds in its root viewmodel class. When all actions are executed the periodic action logic will save any changed state that was the result of your actions.

Periodic actions can be used to “automatically” step your information from one state to the next – given that the circumstances are correct.

This ability might take some getting used to – but it can be used for things like assigning a unique number to an order or an article in your domain model – or for actions that need to be done serverside for some particular reason.

Define the periodic actions in the ViewModelEditor:

ServerSide Actions 01.pngServerSide Actions 02.png

With this technique you can change any and all state of objects in your database in an efficient manner with very little code.

As a common case is the need to assign a unique number I will show this. The client cannot alone be used to guarantee that the next number in a sequence is taken, since there may be multiple users trying to do this at the same time. We need to make sure we serialize all user requests for a new number. This is commonly done with a database lock. There is however a nice alternative to a harsh db-locking technique and that is to serialize via a server side action.

Consider having this state machine:

ServerSide Actions 03.png

The ViewModel associated with the periodic action on the server can now assign my number.

ServerSide Actions 04.png

The client will set the AssignNumber state. The Server side action will look for

Order.allinstances- >select(o|o.State=’AssignNumber’)

When objects are found they will be assigned a new number by the actions in the ServerSide ViewModel and saved. Combined with a periodic client action that calls selfVM.Refresh we will see on the client as soon as state is changed to NumberAssigned.

Since we do not want the client to poll selfVM.Refresh all the time we set the EnableExpression in this action to self.State=’AssignNumber’.

Following this pattern we get the user pushing a button to get a new number, we can show some info about working – the client starts refreshing – the server does its job – the client gets the new info by its refresh – the info abut progress can be hidden as a consequence. This way we have serialized an action in our system with model driven techniques that will scale well and work of any number of users of your system.

Other uses of Server side Actions

We have also implemented several additional common actions that you can have the MDrivenServer perform for you.

Emailing from the server

If you have an action in your viewmodel named “email” then MDrivenServer will try to find the following properties in your viewmodel:

to : will be used as to email address. You can also send in multiple emails in a comma separated string to send to multiple. Use this syntax PopularName<email> to get a common name to show instead of the email

topresentation: the name of the owner of the email this is replaced by sending in PopularName<email> in the "to" column as described here

from: the sender email

frompresentation: the name to use as sender

body: the message

subject: the subject line

Emailxxx: Any action starting with email will trigger the send.

The properties found will be used to send an email – you need to fill in the email settings in the admin UI for this to work

Emailing from the server has been updated to allow for attachments as described here; send email with attachments

Importing data from other SQL sources

MDriven Server has functionality to import data from other sqlbased systems. The ability to read from an external SQL server and import that data – strictly by using MDriven techniques and zero need for external programs.

´Suppose I have this model and I really want class1 to be reference data from an external database:

ServerSide Actions Importing Data 01.png

So I declare a viewModel that looks like this:

ServerSide Actions Importing Data 02.png

It defines 4 columns with data and 2 actions:

1=ViewModel / new Nesting – the name of yet another viewmodel that will act as a importer of the sql result set , this can in recent version be replaced with Nesting and then you are expected to a have a connected nesting with that name in the ViewModel that has the Import action. This Nesting is then defining the columns to import.

This show how Nesting column ties to Nesting inside same viewmodel

2=Connectionstring- the external database (Update 2018-10-18: you can now use 'connectionstringodbc' and the logic will use ODBC connection instead of sqlserver.)

3=Query – the sql query – remember that you can build it with data from the rest of your model

4=Key – if we want the import to be able to update Class1 we need to explain what the key is in the class

And the actions:

SQLImport – using this name will trigger the import function in MDriven Server

Finished – this is a generic action – that just execute the expression – in this case setting Class2.Attribute1 to ‘Done’

So the SQL data returned looks like this:

ServerSide Actions Importing Data 03.png

And the ViewModel that is going to act as the import template – called “TheImporter” in the example above looks like this:

ServerSide Actions Importing Data 04.png

I now declare the ServerSide job in MDriven server:

ServerSide Actions Importing Data 05.png

Now the MDriven Server will check every 20:seconds if the expression

Class2.allinstances- >select(attribute1=’todo’)

returns any rows. If it does – it fetches at most 2 of these and executes all the actions found in TheServerSideJob.

In MDriven Designer I can create a Class2 with the debugger and save it:

ServerSide Actions Importing Data 06.png

And then I check the MDriven Server log: ServerSide Actions Importing Data 07.png

I then check my Class2: ServerSide Actions Importing Data 08.png

Attribute1 is now ‘Done’ – so the serverside job relaxes and will not find anything more to do just now…

More about exporting