Eventhandler and Replication – Best practice

Hey,

some time ago I faced some problems with the Vault-API in the eventhandler. As always, the problems were discovered only on the customer side. After some analysis we found the reason for the issuese: The Problems occured only in a replicated environment.

And here is my eventhandler class for the Vault 2013 Server:

[assembly: ApiVersion("5.0")]

[assembly: ExtensionId("some guid here")]

       public class Eventhandler : IWebServiceExtension
       {

internal EventHandler<CheckinFileCommandEventArgs> CheckInEventhandl;
             internal EventHandler<AddFileCommandEventArgs> AddEventhandl;
             internal EventHandler<DeleteFileCommandEventArgs> DelEventhandl;
             internal EventHandler<MoveFileCommandEventArgs> MoveEventhandl;
             private WebServiceManager _webSvcMgr;

             public void OnLoad()
             {
                    AddEventhandlers();
             }

...

             void AddFileEventPost(object sender, AddFileCommandEventArgs e)
             {
                    …     
             }
             void CheckinFileEventPost(object sender, CheckinFileCommandEventArgs e)
             {
                    …
             }

             void MoveFileEventPost(object sender, MoveFileCommandEventArgs e)
             {
                    …
             }
             void DelFileEventPre(object sender, long fMid, DeleteFileCommandEventArgs e)
             {
                    …                  
             }
             void DelFilesEventPre(object sender, DeleteFileCommandEventArgs e)
             {
                    foreach (var fileMasterId in e.FileMasterIds)
                    {
                           DelFileEventPre(sender,fileMasterId,e);
                    }
             }
…

             private void AddEventhandlers()
             {
                    CheckInEventhandl = CheckinFileEventPost;
                    AddEventhandl = AddFileEventPost;
                    DelEventhandl = DelFilesEventPre;
                    MoveEventhandl = MoveFileEventPost;
                    DocumentService.CheckinFileEvents.Post += CheckInEventhandl;
                    DocumentService.AddFileEvents.Post += AddEventhandl;
                    DocumentService.DeleteFileEvents.Pre += DelEventhandl;
                    DocumentService.MoveFileEvents.Post += MoveEventhandl;
             }

             private void RemoveEventhandlers()
             {
                    DocumentService.CheckinFileEvents.Post -= CheckInEventhandl;
                    DocumentService.AddFileEvents.Post -= AddEventhandl;
                    DocumentService.DeleteFileEvents.Pre -= DelEventhandl;
                    DocumentService.MoveFileEvents.Post -= MoveEventhandl;
             }
       }

( And I have installed the latest version of the sdk-assemblies: v 17.0.62.0 )

Problem 1)

When I work with my VaultExplorer-Client on the replicated environment (there is no difference if I work on Publisher or on Subscriber) I realized that some of the events becomes fired twice!

This is the result of my analysis:

– AddFileEvent          (POST):          becomes fired 2 times

– CheckinFileEvent    (POST):          becomes fired 1 time

– MoveFileEvent        (POST):          becomes fired 2 times

– DeleteFileEvent      (PRE):             becomes fired 1 time

I analyzed, that both events have always different Event-Id (GUID)

This problem is reproducible and happens only in a replicated environment!

Problem 2)

Scenario:

PUBSLISHER adds a file and changes the ownership to him.

SUBSCRIBER changes the ownership of a folder to the Subscriber.

PUBLISHER moves his file to the Subscriber

In This scenario the move-event becomes blocked with an Error-message, but the movefile-event was fired anyway! This means we have a problem, because the file doesn’t become moved, but the event was fired!

Solutions:

Problem 1)

In fact, here we are talking about an API issue, where we a workaround: You have to overload the pre-event AND the post-event. Then you have to remember that the pre-event was called allready. So you can check later if you are running in the first Post-event, and the second post-event can be terminated.

Do like this:

1) create a internal variable where you are chaching the pre events:

public class Eventhandler : IWebServiceExtension
{
   internal Dictionary<long,FileInfos> DeleteFileCache;
   ...

2) overload also the Pre-event and create a cache functionality for it:

void DelFilesEventPre(object sender, DeleteFileCommandEventArgs e)
{
   foreach (var fileMasterId in e.FileMasterIds)
   {
      DelFileEventCache(sender, fileMasterId, e);
   }
}
void DelFileEventCache(object sender, long fMid, DeleteFileCommandEventArgs e)
 {
    SetWebSrvMngr(sender);
    if (!DeleteFileCache.ContainsKey(fMid))
    {
       DeleteFileCache.Add(fMid, FileInfo);
    }
    else
    {
       Logger.Log.WarnFormat("A file with this MasterId was allready found in the cache (Mid: {0} )! Stopping ...", fMid);
    }
}

3) And now create the post functionality and check if the pre-function was fired allready. If we are in the second post event, just return:

void DelFilesEventPost(object sender, DeleteFileCommandEventArgs e)
{
   foreach (var fileMasterId in e.FileMasterIds)
   {
      DelFileEventPost(sender,fileMasterId,e);
   }
}
void DelFileEventPost(object sender, long fMid, DeleteFileCommandEventArgs e)
{
   if(!DeleteFileCache.ContainsKey(fMid))
   {
      Logger.Log.ErrorFormat("Failed to find the file in the cache (Mid: {0} )! Stopping ...",fMid);
      return;
   }
   DeleteFileCache.Remove(fMid);

   //do your stuff here
   ...
}

Problem 2)

Always check the Status property on the EventArgs during a Post. See here:

void CheckinFileEventPost(object sender, CheckinFileCommandEventArgs e) 
{
    if(!CheckEventStatus(sender, e))
       return;
    ...
}

private bool CheckEventStatus(object sender, WebServiceCommandEventArgs eventArgs)
{
   if(eventArgs.Status!=EventStatus.SUCCESS)
   {
      return false;
   }
   return true;
}

I hope this was helpful for you as a Vault-Eventhandler developer :)

About weiss92

Software Developer
This entry was posted in Vault API, Visual Studio and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s