Skip to main content

PreDisconnect Trigger

  • PreDisconnect Trigger programs are executed while a Relationship Instance is being disconnected, before the platform code for disconnect executes.
  • They are used to validate or manipulate the relationship based on business requirements.
  • They are executed synchronously, i.e. in the same transaction as the relationship disconnect.
  • They are executed before standard validations are executed by the platform code.

Coding guidelines

  • PreDisconnect Trigger program is a class that must implement the interface IPreDisconnectTriggerProgramAsync

    public interface IPreDisconnectTriggerProgramAsync
    {
    Task<ProgramResult> RunAsync(Guid relationId);
    }

    NOTE: Use IPreDisconnectTriggerProgramAsync with the RunAsync method.

  • Protrak runtime passes the relationId of the relationship being disconnected to the trigger.

  • If you need relation details or the related instances, fetch them explicitly before making decisions.

  • Program should return a ProgramResult object:

    • If IsSuccess is true, then the trigger execution is considered as successful.
    • If IsSuccess is false, then the trigger is considered as failed, subsequent code is not executed, and the DB transaction is rolled back.
    • If IsSuccess is false, ideally the string[] Errors should be populated with proper error messages which will be returned in API response, which can be displayed to end user.
  • Because the trigger runs before the disconnect, the relation and the linked instances are still available to the trigger.

Typical use cases for PreDisconnect Trigger

  • Validate whether the relationship can be disconnected where some complex business logic is involved.
  • Prevent disconnect when related business data still depends on the relationship.
  • Clean up or adjust instance state before the relation is removed.
  • Remove access or dependent data that must be handled before the relationship goes away.
  • If any validations or cleanup steps need to use a third-party service or integration.

Anti-patterns or when not to use PreDisconnect Trigger

  • Prefer configuration over customization. Avoid using a program when configurable validations or cleanup are possible.
  • Do not use PreDisconnect trigger to make changes that are not reversible, like sending an email. If the disconnect process fails, the transaction will be rolled back, but the side effect would already have happened.
  • Do not assume the relation has already been removed. PreDisconnect runs before disconnect, so queries should be written with that timing in mind.

Sample Code

using Prorigo.Protrak.API.Contracts;
using Prorigo.Protrak.API.Services;
using Prorigo.Protrak.Programs;
using System;
using System.Threading.Tasks;

public class ProjectToTaskPreDisconnectTriggerProgram : IPreDisconnectTriggerProgramAsync
{
public IInstanceService InstanceService { get; set; }
public IRelationService RelationService { get; set; }

private readonly string RELATION_PROJECT_TO_TASK = "ProjectToTask";
private readonly string ATTRIBUTE_TASK_STATUS = "Status";

public async Task<ProgramResult> RunAsync(Guid relationId)
{
var relation = await RelationService.GetRelationAsync(relationId);
if (relation == null)
{
return new ProgramResult
{
IsSuccess = false,
Errors = new[] { "Relationship could not be found." }
};
}

var taskInstance = await InstanceService.GetInstanceAsync(relation.DestinationInstanceId, new[] { ATTRIBUTE_TASK_STATUS });
var status = taskInstance?.GetTextAttributeValue(ATTRIBUTE_TASK_STATUS);

if (string.Equals(status, "Closed", StringComparison.OrdinalIgnoreCase))
{
return new ProgramResult
{
IsSuccess = false,
Errors = new[] { "Closed tasks cannot be disconnected from the project." }
};
}

return new ProgramResult { IsSuccess = true };
}
}

Note: The Run method (from IPreDisconnectTriggerProgram) is available for legacy synchronous implementations.