You can merge the SysAsync package into your MDriven Designer model to create background-work tickets that MDrivenServer recognizes and executes.
What this package adds
The SysAsync package provides the SysAsyncTicket model pattern. A ticket records what MDrivenServer should execute later in its server context, so that work can run in the background rather than as part of the user's current action.
Use this pattern when an action should request work and continue without waiting for that work to finish. For example, a Customer action can create a ticket that assigns the next customer number.
The package is an important architectural pattern. For the ticket lifecycle and execution behavior, see Documentation:AsyncTicket. For scheduled and reactive server work more broadly, see Documentation:Serverside jobs.
Download and merge the package
Download SysAsyncTicketMergeModel.modlr, then merge it into the model that needs background work.
- Open the target model in MDriven Designer.
- Choose open merge add.
- Select
SysAsyncTicketMergeModel.modlr. - Review the merged model content and save the target model.
- Deploy the updated model to the MDrivenServer environment that will process the tickets.
When you merge a .modlr file, existing classes with the same name receive the incoming class content; the incoming duplicate class is discarded. Content from a package with the same package name is moved into the existing package. Incoming ViewModels with names that already exist are skipped, while new ViewModels are added. See Documentation:Model Examples Old for the merge behavior and other mergeable model patterns.
Create a background ticket
Create a SysAsyncTicket in the action that requests the work. Set:
| Property | Set it to | Example |
|---|---|---|
RootObject
|
The object on which the server should perform the work. | self for the Customer being updated.
|
ViewModel
|
The method or server-side ViewModel that MDrivenServer should invoke. | 'Customer.AssignNumber'
|
Priority (optional)
|
A nullable integer that controls queue order when the property exists in the model. | 1 for work that should be selected before tickets with priority 10.
|
For a method on Customer, create the ticket in OCL (Object Constraint Language) as follows:
let ticket = SysAsyncTicket.Create in (
ticket.RootObject := self;
ticket.ViewModel := 'Customer.AssignNumber'
)This requests that MDrivenServer call AssignNumber on the Customer object in server context. The method should protect against being run more than once when that matters. For example, an AssignNumber method can have the precondition self.CustomerNumber->isNull before it increments and assigns the next number.
Invoke a server-side ViewModel instead
Invoking a method is different from invoking a server-side ViewModel. To invoke a server-side ViewModel with a Customer as its root object, set ViewModel to the ViewModel reference:
let ticket = SysAsyncTicket.Create in (
ticket.RootObject := self;
ticket.ViewModel := Customer.ViewModels.SomeViewModel
)Use the method form when the ticket should call a named method. Use the server-side ViewModel form when the work is implemented as a server-side ViewModel. See Documentation:AsyncTicket for the full ticket pattern.
Prioritize queued work
Add a nullable integer property named Priority to SysAsyncTicket when you need queue ordering. MDrivenServer orders available tickets by this property; lower numbers are selected first. A ticket with priority 1 is selected before a ticket with priority 10 when both are available for selection.
For example, give a short user-requested operation priority 1 and a longer non-urgent operation priority 10:
let ticket = SysAsyncTicket.Create in (
ticket.RootObject := self;
ticket.ViewModel := 'Customer.AssignNumber';
ticket.Priority := 1
)Priority affects the order in which queued tickets are selected. It does not change the work performed by the method or ViewModel.
Avoid subclass synchronization errors
When the root object is an instance of a subclass, name the method using the object's actual runtime type. Do not name it only with a superclass type.
For example, if self is a SubClassOfThing, this can cause synchronization problems:
ticket.ViewModel := 'Thing.AssignNumber'Use the subclass name instead:
ticket.ViewModel := 'SubClassOfThing.AssignNumber'For code that must work for different subclasses, build the method reference from the object's type:
ticket.ViewModel := self.oclType.asstring + '.AssignNumber'This matters because MDrivenServer records the changed object's type for synchronization. If the ticket names the superclass while the object is actually a subclass, a client refresh can be notified about a changed superclass object that it cannot associate with the subclass instance.
