Server call optimization


<< Prev   Next >>

Scope: managed applications, mobile applications, and ordinary applications.

1.1. When you develop a managed application, pay attention to how many messages the client sends to the server—that is, the number of server calls and, for some cases, the volume of network traffic.

The total number of server calls is comprised of:

  • Calls made by 1C:Enterprise platform, and
  • Calls from the application code.

As a general approach, try to keep the number of server calls as low as possible, providing that the application users will be able to carry out their tasks in a reasonable time and with reasonable quality. Any architectural decisions that result in more server calls should be well-argued and data-driven.

A common exception is an implicit server call at the first call to the client common module. For example, calling TradeOffersClient.UpdateOffers will result in a server call if the TradeOffersClient common module has not been compiled yet.

1.2. For the slow connection mode and mobile client, consider optimizing the amount of data transferred between the client and the server. To get relevant results when debugging the client/server communication in this mode, use a network latency tool to simulate a delay.

Below you can find the best practices on how to optimize client/server communication.

Starting client application

2.1. In basic cases, the configuration code, which runs at the application start, does not send any requests to the server. This refers to the code of the BeforeStart and OnStart application module handlers. In other cases, follow these recommendations:

  • Do not call server procedures and functions directly from the application modules, managed application modules, or external connection modules.
  • Correct example: within a single server call, pass all parameters required to start an application to the client.

If the startup parameters are required by different modules, place the function that sends the request into a memoization module. On the first call, the function sends one request to the server and then caches the parameters. The next time the function is called in this session, it returns the cached values.

Example:

// A snippet of the ParametersCached common server memoization module.
 Function ClientRunParameters()
 Parameters = New Structure();
 Parameters.Insert("FileInfobase", Common.FileInfobase());
 // Initialization of the startup parameters.
 // Parameters.Insert(parameter name, parameter value);
 Return Parameters;
 EndFunction

Example of the ClientRunParameters function used in the OnStart handler on the client side:

FileInfobase = ParametersCached.ClientRunParameters().FileInfobase;
 If FileInfobase Then
 // The event is handled on the client side
 //…

2.2. For configurations that embed Standard Subsystems Library (SSL), use the built-in API:

  • Place the server code to start the application in the OnAddClientParametersOnStart or OnAddClientParameters procedures of the CommonOverridable common module.
  • On the client side, call the ClientParametersOnStart or ClientRunParameters functions of the StandardSubsystemsClient common module whose result is cached upon the first call.

For more information, see the comments to these procedures and functions and implementation examples in the SSL demo infobase.

See also: Cashing values that affect application behavior

Periodic server calls

3.1. In some cases, you need to periodically transfer data from the client to the server or perform periodic checks of the server status, for example:

  • Transfer data on performance measurements and client parameters.
  • Check dynamic configuration changes or user right changes with a prompt to restart the application.
  • Check whether user sessions are closed.
  • Check whether exchange rates are up-to-date with a prompt to update them.
  • Check user reminders with notifications.

To do this, combine calls into one with a one-minute period if possible. Besides, we recommend that you use the Collaboration System to send notifications to client sessions from the server instead of periodic calls from the client to check the server state.

3.2. For configurations that embed Standard Subsystems Library (SSL), use the built-in API.

3.2.1. For long-running operations, use the WaitCompletion procedure of the TimeConsumingOperationsClient common module to wait for the operation result.

3.2.2. To check the server state for a separately opened form without long-running operations, you can make context-less (fast) server calls. Choose the longest call period possible for this task. For example, when updating the state in the form of exchanging data on the scheduled job progress.
 For forms on the home page, we do not recommend that you make periodic server calls. Instead, create an Update button. If periodic calls are required, keep them disabled by default and set the period to no longer than one minute. For example, in the To-do list form.

3.2.3. To periodically check the server state and send notifications to client sessions:

  • Add a description of the periodic server notification in the OnAddServerNotifications procedure of the CommonOverridable common module.
  • Implement the procedure for sending notifications from the Send server notifications to clients scheduled job in the OnSendServerNotification procedure of the common module specified in the server notification description.
  • Implement the procedure for processing the received notification on the client in the OnReceiptServerNotification procedure of the common module specified in the server notification description.

3.2.4. To periodically send data from the client to the server:

  • Place client code for adding data to send to the server in the BeforeRecurringClientDataSendToServer procedure of the CommonClientOverridable common module.
  • Place server code for processing data received from the client in the OnReceiptRecurringClientDataOnServer procedure of the CommonOverridable common module.
  • Place client code for processing data returned from the server in the AfterRecurringReceiptOfClientDataOnServer procedure of the CommonClientOverridable common module.

For more information, see the comments to these procedures and implementation examples in the SSL demo infobase.

Opening managed forms

4.1. If a form is opened programmatically, employ the OpenForm global context method and get all the required data in a single call. For 1C:Enterprise version 8.2 or earlier, you can also use the OpenFormModal method. Pass the parameters to the form with the Parameters method parameter.

4.2. When a form is opened, the form event handlers such as OnOpen and OnReopen must not call the server. If they require data stored on the server, copy this data into the form's attributes with the event handler OnCreateAtServer.

For example, it is incorrect to start a background job with long-running calculation in the OnOpen event handler. Instead, start it in OnCreateAtServer and check its availability in OnOpen. For more information, see Time-consuming operations on the server.

Another incorrect example:

ProxyServerSetting = ServerModule.ProxyServerSetting();
 OpenForm("CommonForm.ProxyServerParameters", New Structure("Settings", ProxyServerSetting));

Correct example:

OpenForm("CommonForm.ProxyServerParameters");

To get the constant value, use the OnCreateAtServer event handler of the ProxyServerParameters form.

When opening the form, do not call memorization server functions as their result is cached only after the first call. It means that when you open the form for the first time, redundant server calls occur.

4.3. When you open the form, do not attach multiple idle handlers (using the AttachIdleHandler method) that check if started background jobs are ready and update the form data. For example, these handlers display on the form various control results or additional information whose preparation takes much time. Attaching multiple idle handlers leads to redundant server calls.

We recommend that you combine various handlers of background job completion into one handler that checks the readiness and takes a result from the server in a single call. In general, you can also combine background jobs into one to increase the server performance. If the handler is attached periodically, select a handler start interval according to the recommendations in the article Time-consuming operations on the server.

For configurations that embed Standard Subsystems Library, start long-running operations using the API in the TimeConsumingOperations and TimeConsumingOperationsClient common modules. The API provides tools for combining various handlers for background job completion into one handler with an optimal start interval to optimize server calls.

Executing local commands

5.1. No more than one request to the server is allowed when a user runs a local command.

If a local command processes data on the client side only, such as filtering a list or modifying formatting, the required data must be imported to the client side in advance. We recommend that you prepare this data in advance in the OnCreateAtServer form event handler and place it in the form attributes.

Example:
When goods are selected from the list, it is required to restrict product group selection for users. Whenever a user attempts to select a product group, the application must display a warning. Incorrect: call a server function to check if the list item is a product group. Correct: add a Boolean attribute IsFolder to the value table that provides the data for the list. The attribute value is populated by the OnCreateAtServer event handler. In this case, the group-or-not check will not send requests to the server.

CurrentRow = Item.CurrentData;
If CurrentRow.IsFolder Then
 Message = New UserMessage();
 Message.Text = NStr("en = 'You cannot select groups.'");
 Message.Message();
 Return;
 EndIf;

However, if a command cannot deliver its purpose without getting some data from the server, the data must be requested in a single server call.

Selecting from catalogs

5.2. No more than one request to the server, which is made by the global context method OpenForm or OpenFormModal, is allowed when a user selects an item from a catalog.

5.3. If the business logic requires processing data on the server side after the selection, it must be done by another single server call.

Executing global commands

6.1. No more than one request to the server is allowed when a user runs a global command. If the command opens a form, the call is made by the OpenForm or OpenFormModal global context method.

Generating reports

7.1. No additional server calls are allowed when a report is being generated.

In particular, server calls are not allowed from procedures that handle form events, such as OnOpen and OnReopen.

Incorrect: generate a report that uses Data Composition System with the OnOpen event handler.

&AtClient
 Procedure OnOpen(Cancel)
 OutputReport();
 EndProcedure

&AtServer
 Procedure OutputReport()
 // Code to generate the report.
 EndProcedure

Correct:

  • Open the report form with its GenerateOnOpen parameter set to True.
  • Or set the GenerateOnOpen parameter to True in the OnCreateAtServer event handler.

Batch item selection

8.1. One of the specifics of the client/server architecture is that the list of selected items is transferred between the object form and the pick form. Note that the volume of the transferred data might be quite large.

If the amount of the transferred data is expected to be large, it is not recommended that you send it as a pick form parameter. Since managed forms are optimized, when you try to send a large amount of data stored in the FormDataCollection parameter, some of it might be missed on the client. As a result, the client will have to make another request to the server to get the rest of the data.

8.2. To optimize data exchange between object forms and pick forms, use a temporary server-side storage.

Example. A user fills the Goods table of the SalesInvoice document from the Goods catalog.

When a pick form is opened, no more than two server calls can be made. With the first call, the local command of the SalesInvoice document copies the list of goods from the table to the temporary storage. With the second call, it opens the selection form and passes the storage address:

// In the document form
 &AtClient
 Procedure PickingCommandHandler()
 GoodsAddressInStorage = PutGoodsInStorage();
 PickingParameters = New Structure();
 PickingParameters.Insert("DocumentGoodsAddress", GoodsAddressInStorage);
 PickingParameters.Insert("PricesKind ", Object.PricesKind);
 PickingParameters.Insert("Warehouse ", Object.Warehouse);

PickForm = OpenForm("Document.SalesInvoice.Form.PickForm", PickingParameters, Items.Goods);
 EndProcedure

 // The function saves the list of goods to the temporary storage and returns the address.
 &AtServer
 Function PutGoodsInStorage()
 Return PutToTempStorage(Object.Goods.Unload(,"Goods,Price,Count"), UUID);
 EndFunction

The pick form receives a list of goods selected from the temporary storage in the OnCreateAtServer handler:

// In the pick form
 &AtServer
 Procedure OnCreateAtServer(Cancel, StandardProcessing) Export
 // Save the temporary storage address to put the selected goods back into it.
 DocumentGoodsAddress = Parameters.DocumentGoodsAddress;
 Object.Goods.Load(GetFromTempStorage(GoodsAddress));
 EndProcedure

When the pick form is closed, no more than two server calls can be made. With the first server call, when the user closes the pick form, it places the selected goods into the temporary storage.

&AtClient
 Procedure OKExecute()
 GoodsAddressInTempStorage = WriteFillToStorage();
 NotifyChoice(GoodsAddressInTempStorage);
 EndProcedure

 &AtServer
 Function WriteFillToStorage()
 Return PutToTempStorage(Goods.Unload(), DocumentGoodsAddress);
 EndFunction

The document form restores a list of goods from the temporary storage (second server call):

// Process selected items of the Goods form table.
&AtClient
 Procedure OnProcessSelectedGoods(Item, GoodsAddressInStorage, StandardProcessing) Export
If GoodsAddressInStorage = Undefined Then
 Return;
EndIf;
 GetGoodsFromStorage(GoodsAddressInStorage);
EndProcedure

&AtServer
 Procedure GetGoodsFromStorage(GoodsAddressInStorage)
SelectedGoods = GetFromTempStorage(GoodsAddressInStorage);
 Object.Goods.Load(SelectedGoods);
DeleteFromTempStorage(DocumentGoodsAddress); // Temporary storage is cleared to minimize RAM consumption.
 EndProcedure

8.3. When you place data in a temporary storage, choose one of the following options:

  • Place data in a temporary storage for the form lifetime using the form UUID and clear this temporary storage after use. For an example, see it. 8.2.
  • Pre-initialize the temporary storage and reuse it.

Otherwise, if an action in the form is repeated several times (for example, on multiple selection of goods), it leads to excessive RAM consumption.

Here is an example of how to pre-initialize the temporary storage for reuse:

&AtServer
 Procedure OnCreateAtServer(Cancel)
 GoodsAddress = PutToTempStorage(Undefined, UUID); // The form attribute is initialized.
 EndProcedure

 &AtServer
 Function GoodsInTempStorage()
 Return PutToTempStorage(Goods.Unload(), GoodsAddress);
 EndFunction

When reusing the temporary storage, you do not need to delete the value from the temporary storage:

// In the document form
 &AtServer
 Procedure GetGoodsFromStorage(GoodsAddressInStorage)
 SelectedGoods = GetFromTempStorage(GoodsAddressInStorage);
 Object.Goods.Load(SelectedGoods);
 EndProcedure

Writing forms

9. Instead of an additional server call in the BeforeWrite and AfterWrite client handlers of the form module, place the server logic in the similar server handlers: BeforeWriteAtServer, OnWriteAtServer, and AfterWriteAtServer. Then pass the data to the client via the WriteParameters handler parameter or form attributes.

Incorrect:

&AtClient
 Procedure AfterWrite
 FormManagement();
 EndProcedure

&AtServer
 Procedure FormManagement()
 …

Correct: Call the FormManagement procedure in AfterWriteAtServer passing and checking the parameter on the subsequent closing of the form. If the form is closed, it makes no sense to manage it.

Implicit server calls

10. Pay special attention to client methods and properties of platform objects that cause or may cause a server call:

  • The GetFromTempStorage and DeleteFromTempStorage methods.
  • The Title, Enabled, ToolTip, ReadOnly properties of a form field and other.
  • GetInterfaceFunctionalOption and GetFormFunctionalOption.
  • For the full list of such methods and properties, see Syntax Assistant.

Avoid calling such methods and properties of platform objects repeatedly from the client code. Instead, combine them into one server call: use one temporary storage or transfer the logic to a server procedure that is called once from the client.

Do not call memorization server functions as their result is cached only after the first call. It means that during the first call, redundant server calls occur. Refer to it. 4.2 for calls from the form module or it. 2.1 for other calls.

Client/server data transfer

11. Do not transfer more data from the client to the server than is necessary to complete the task. For example, if only one attribute value is required to perform a procedure on the server, do not make a context call.

Incorrect:

&AtClient
 Procedure OnActivateCounterpartiesListRow()
 UpdateContactInformationPanelServer();
 EndProcedure

&AtServer
 Procedure UpdateContactInformationPanelServer()
 ContactInformationPanel.UpdatePanelData(ThisObject, CurrentCounterparty);
 EndProcedure

Correct:

&AtClient
 Procedure OnActivateCounterpartiesListRow()
 UpdateContactInformationPanel();
 EndProcedure

&AtClient
 Procedure UpdateContactInformationPanel()
 PanelData = ContactInformationPanelData(CurrentCounterparty);
 ContactInformationPanelClient.FillContactInformationPanelData(ThisObject, PanelData);
 EndProcedure

&AtServerNoContext
 Function ContactInformationPanelData(Counterparty)
 Return ContactInformationPanel.ContactInformationPanelData(Counterparty);
 EndFunction

12. We do not recommend that you return parameter values from the server to the client. Instead, create a function that will return the required data. Specify all parameters in procedures and functions that are called from the client to the server with the Val prefix. In this case, the value will not be returned from the client to the server entirely, including the contents of complex types, such as Structure and Array.

These are export server procedures placed in common modules with the Server call flag, and procedures in form and command modules with the &AtServer, &AtServerNoContext compilation directives or without directives (implicit &AtServer definition).

Example:

&AtClient
 Procedure CommandProcessing(CommandParameter, CommandExecuteParameters)
 NewConversation = NewConversation(CommandParameter);
 …EndProcedure

Incorrect:

&AtServer
 Function NewConversation(UserRef)
 …
 Return GetURL(Conversation.ID);
 EndProcedure

Correct:

&AtServer
 Function NewConversation(Val UserRef)
 …
 Return GetURL(Conversation.ID);
 EndProcedure

See also:

<< Prev   Next >>

Icon/Social/001 Icon/Social/006 Icon/Social/005 Icon/Social/004 Icon/Social/002