Here is an example for you. I've removed some private code as needed. What is happening is there are 2 custom tables that store info when a user record or preferences are changed/updated. The Integration Bus then runs (async) and gets the data from those custom tables and calls web services to update the primary record within a different system (which is the part I didn't include). The important part is choosing what you want to happen when a sync fails or succeeds. Hope this helps a bit. I spent quite a bit of time reading the integration bus documentation and went from there. Really the base example is not far off from what I've shown below.
Good luck
using CMS.EventLog;
using CMS.SettingsProvider;
using CMS.SiteProvider;
using CMS.Synchronization;
using CMS.SynchronizationEngine;
using System;
/// <summary>
/// Summary description for IntegrationConnector
/// </summary>
public class IntegrationConnector : BaseIntegrationConnector
{
#region Initialization (subscribing)
public override void Init()
{
// Initialize connector name (it has to match the code name of connector stored in DB)
ConnectorName = GetType().Name;
SubscribeToObjects(TaskProcessTypeEnum.AsyncSnapshot, "customtableitem.mynamespace.usersync", TaskTypeEnum.CreateObject);
SubscribeToObjects(TaskProcessTypeEnum.AsyncSnapshot, "customtableitem.mynamespace.emailpreferencesync", TaskTypeEnum.CreateObject);
}
#endregion
#region Internal (outgoing) tasks
/// <summary>
/// Processes given object according to task type.
/// It is expected that you use TranslateColumnsToExternal method before you process the task.
/// The TranslateColumnsToExternal needs GetExternalObjectID and GetExternalDocumentID to be implemented.
/// It traverses the given object and tries to translate foreign keys to match external (your) application.
/// </summary>
/// <param name="infoObj">Info object to process</param>
/// <param name="translations">Translation helper object containing translations for given object</param>
/// <param name="taskType">Type of task</param>
/// <param name="dataType">Type of data</param>
/// <param name="siteName">Name of site</param>
/// <param name="errorMessage">Possible error message</param>
/// <returns>Result of processing</returns>
public override IntegrationProcessResultEnum ProcessInternalTaskAsync(GeneralizedInfo infoObj, TranslationHelper translations, TaskTypeEnum taskType, TaskDataTypeEnum dataType, string siteName, out string errorMessage)
{
try
{
CustomTableItem cti = (CustomTableItem)infoObj;
string msg = "";
IntegrationProcessResultEnum returnResult = IntegrationProcessResultEnum.OK;
switch (infoObj.ObjectType.ToLower())
{
case "customtableitem.mynamespace.emailpreferencesync":
switch (taskType)
{
case TaskTypeEnum.CreateObject:
int acctNum = cti.GetIntegerValue("acctNumber", 0);
if (acctNum > 0)
{
#region Process Estatement
// do some work here
if (!MyProvider.SetEmailPreferences(acctNum, UserReceiveBalanceWithin, UserReceiveExceedBalance, UserExceedBalance, UserReceivePaymentAlert, ref EmailAlertsErrorMessage))
{
// set return values
msg += "Error syncing email preferences for account " + acctNum.ToString() + ". Error message: " + EmailAlertsErrorMessage;
returnResult = IntegrationProcessResultEnum.SkipNow;
}
#endregion Process Email Preferences
}
if (returnResult == IntegrationProcessResultEnum.OK )
{
// delete the existing custom table item because it succeeded
}
errorMessage = msg;
return returnResult;
default:
errorMessage = null;
return IntegrationProcessResultEnum.OK;
}
break;
case "customtableitem.mynamespace.usersync":
// do some other work here
break;
default:
errorMessage = null;
return IntegrationProcessResultEnum.OK;
}
}
catch (Exception ex)
{
errorMessage = ex.Message;
return IntegrationProcessResultEnum.ErrorAndSkip;
}
finally
{
// Clear translations cached during TranslateColumnsToExternal which internally calls GetExternalObjectID, GetExternalDocumentID
// This call is optional but recommended in the case where eg. collision of code names can occur
ClearInternalTranslations();
}
}
#endregion
#region External (incoming) tasks
#endregion
}