Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tridion - Event System Objects are Not Being Destroyed

I have created a TcmExtension named WorkflowEventSystem that has an event handler subscribed to the FinishProcess event. The purpose of this event is to schedule for publish all dependencies (i.e. pages) of the associated workflow subject.

The problem I am having is that even though the event triggers at the right time (a workflow process is completed), and all the items that are supposed to be scheduled for publish are, the PublishScheduler object created by the event never seems to go out of scope, and as such the WorkflowEventSystem object does not either.

Is there something I am missing about how the Event System works that would cause these objects to live on forever? I've included what I consider the relevant code below (some parts summarized). Thanks for any help.

Here's most of the actual TcmExtension:

public class WorkflowEventSystem : TcmExtension
{
    public WorkflowEventSystem()
    {
        this.Subscribe();
    }

    public void Subscribe()
    {
        EventSystem.Subscribe<ProcessInstance, FinishProcessEventArgs>(ScheduleForPublish, EventPhases.All);
    }
}

ScheduleForPublish creates a PublishScheduler object (class I created):

private void ScheduleForPublish(ProcessInstance process, FinishProcessEventArgs e, EventPhases phase)
{
    if(phase == EventPhases.TransactionCommitted)
    {
        PublishScheduler publishScheduler = new PublishScheduler(process);
        publishScheduler.ScheduleForPublish(process);
        publishScheduler = null;  // worth a try
    }
}

The ScheduleForPublish method looks similar to this:

public void ScheduleForPublish(ProcessInstance process)
{
    using(Session session = new Session("ImpersonationUser"))
    {
        var publishInstruction = new PublishInstruction(session);
        // Set up some publish Instructions

       var publicationTargets = new List<PublicationTarget>();
       // Add a PublicationTarget here by tcm id

       IList<VersionedItem> itemsToPublish = new List<VersionedItem>();
       // Add the items we want to publish by calling GetUsingItems(filter)
       // on the workflow process' subject

       //Publish the items
       PublishEngine.Publish(itemsToPublish.Cast<IdentifiableObject>(), publishInstruction, publishTargets);
    }    
}
like image 431
Andrew Keller Avatar asked Aug 27 '12 20:08

Andrew Keller


1 Answers

Life-cycle management for TcmExtension classes is quite simple:

  1. when you call Subscribe the TcmExtension object you specify is added to an internal list of subscriptions

  2. when you later call Unsubscribe the same TcmExtension object is removed from the list of subscriptions

Since you never call Unsubscribe your WorkflowEventSystem is never removed and thus will never be garbage collected by .NET. And since your WorkflowEventSystem holds a reference to the PublishScheduler instance it created, that one will thus also never be cleaned up.

The proper boilerplate for a custom TcmExtension is:

public class WorkflowEventSystem : TcmExtension, IDisposable
{
    EventSubscription _subscription;

    public WorkflowEventSystem()
    {
        this.Subscribe();
    }

    public void Subscribe()
    {
         _subscription = EventSystem.Subscribe<ProcessInstance, 
             FinishProcessEventArgs>(ScheduleForPublish, EventPhases.All);
    }

    public void Dispose()
    {
        _subscription.Unsubscribe();
    }
}

Nuno also gave a longer example (handling multiple subscribers) in this article: http://nunolinhares.blogspot.nl/2012/07/validating-content-on-save-part-1-of.html

like image 71
Frank van Puffelen Avatar answered Dec 03 '22 21:12

Frank van Puffelen