Skip to main content
Skip table of contents

Synchronization Engine Concurrency

This topic describes how concurrency in bidirectional synchronization scenarios is managed. Outbound messages can be grouped by target or link. Each group of messages is processed on its own nested transaction. At the beginning of each nested transaction, a hook on the target is called, which allows the target to take precautions against conflicts from concurrently running processes. In the case of Exchange Sync, the hook is used to acquire a lock on the ExchangeFolder (SysSyncLink).

Exchange Inbound Synchronization

When inbound synchronization is initiated, synchronization metainformation (such as SyncTarget and SyncFolder) is loaded from the database. The ExchangeFolderLock instance associated with the folder being synchronized is locked, to prevent database updates from concurrently running inbound synchronization processes on the same folder, and to avoid reading partial changes generated by concurrently running outbound synchronization processes. Inbound changes are then read from Exchange using one or more service requests. The bulk of the database updates are performed in one or several nested transaction, after which some additional updates to TaskSeries and to SyncObjects may be performed.

MDemko_InboundSequence2D.png

Exchange Outbound Synchronization

Outbound synchronization is initiated when a transaction with changes to synchronized instances commits. The originating transaction posts, through JMS, one or more SyncCommands to send updates to the external system. These requests may be generated asynchronously on one or more additional transactions (not shown in the diagram below). The originating transaction commits the changed instances to the database before a SyncCommand is invoked.

At some later time, the SyncCommand is read through queues. All instances specified by the originating transaction, along with associated meta-information (such as syncObjects, syncGroups, or syncLinks) are reloaded from the database. The instances are parsed into ObjectMessages; if any instances change during the parsing process, then the SyncCommand fails and is later retried. Messages are grouped by folder. For each folder, a separate transaction is run.

The first action on each nested transaction is to lock the ExchangeFolderLock associated with the folder, to prevent Exchange update operations from conflicting with other synchronization processes (inbound or outbound). The second action is to read the SyncObjects table, to verify that SyncObjects about to be created have not already been created by another outbound process. The updates (derived from the ObjectMessages) are sent to Exchange in one or several service requests. Interleaved with these service requests, reads may be done on synchronization metainformation that was not previously identified as relevant by the system. All involved syncObjects and syncGroups are updated with the identifiers and versions returned by Exchange. Finally a transaction listener fires to move any draft invitations to the outbox in Exchange, causing them to be sent. In the event of rollback, the transaction listener will remove any newly created items. This ensures that no items are created in Exchange for which there are no corresponding SyncObjects.

MDemko_OutboundSequence2D.png

The "transaction listener" mentioned above is specifically designed for outbound synchronization with non-transactional targets. It allows some operations to be deferred until after the unit of work commits changes to the database. A call to nexj.core.runtime.FunctionSynchronization'submit registers a listener that will be called whenever the current transaction is committed or rolled back.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.