19

A partner has experienced a locking issues of Job Queue Entry table when sending Records to Dataverse. Sometimes the "Integration Table Mapping" table is locked and sometimes the "Job Queue Entry" table is locked.


Upon further investigation they have shared that this is due to a recursive call of processes and that these will never end in an endless loop but can end in a deadlock such in their case.


This is the callstack of the error:

AL ErrorCode:NDBCS:Deadlock Connection type:Background Message: Message not shown because the NavBaseException constructor was used without privacy classification StackTrace: 

"Job Queue Entry"(Table 472).DeleteTasks line 2 - Base Application by Microsoft 

"CRM Int. Table. Subscriber"(CodeUnit 5341).OnAfterDeleteIntegrationTableMapping line 10 - Base Application by Microsoft 

"CRM Int. Table. Subscriber"(CodeUnit 5341).OnCleanupAfterJobExecution line 15 - Base Application by Microsoft 

"Job Queue Entry"(Table 472).CleanupAfterExecution line 16 - Base Application by Microsoft 

"Job Queue Entry"(Table 472).FinalizeRun line 4 - Base Application by Microsoft 

"Job Queue Dispatcher"(CodeUnit 448).HandleRequest line 47 - Base Application by Microsoft 

"Job Queue Dispatcher"(CodeUnit 448).OnRun(Trigger) line 19 - Base Application by Microsoft


They have shared that this is due to 2 event subscriber in the codeunit 5341 "CRM Int. Table Subscriber".

 - OnAfterDeleteIntegrationTableMapping

 - OnCleanupAfterJobExecution


That said, they have also provided us with a possible change which I believe it would benefit our product greatly and will provide better functionality to our partners and customers: (Change in capital letters)


.........


  [EventSubscriber(ObjectType::Table, Database::"Job Queue Entry", 'OnAfterDeleteEvent', '', false, false)]

  local procedure OnCleanupAfterJobExecution(var Rec: Record "Job Queue Entry"; RunTrigger: Boolean)

  var

    IntegrationTableMapping: Record "Integration Table Mapping";

    RecordID: RecordID;

    RecRef: RecordRef;

  begin

    if Rec.IsTemporary() then

      exit;


    RecordID := Rec."Record ID to Process";

    if RecordID.TableNo() = DATABASE::"Integration Table Mapping" then begin

      RecRef := RecordID.GetRecord();

      RecRef.SetTable(IntegrationTableMapping);

      if IntegrationTableMapping.Get(IntegrationTableMapping.Name) then

        if IntegrationTableMapping."Delete After Synchronization" then

          IntegrationTableMapping.Delete(true);

    end;

  end;


.........


  [EventSubscriber(ObjectType::Table, Database::"Integration Table Mapping", 'OnAfterDeleteEvent', '', false, false)]

  procedure OnAfterDeleteIntegrationTableMapping(var Rec: Record "Integration Table Mapping"; RunTrigger: Boolean)

  var

    JobQueueEntry: record "Job Queue Entry";

  begin

    if Rec.IsTemporary() then

      exit;


//+CHANGE

if IntegrationTableMapping."Delete After Synchronization" then

  exit;

//-CHANGE


    JobQueueEntry.SetRange("Object Type to Run", JobQueueEntry."Object Type to Run"::Codeunit);

    JobQueueEntry.SetFilter("Object ID to Run", '%1|%2', Codeunit::"Integration Synch. Job Runner", Codeunit::"Int. Uncouple Job Runner");

    JobQueueEntry.SetRange("Record ID to Process", Rec.RecordId());

    JobQueueEntry.DeleteTasks();

  end;


.........



Category: Development
STATUS DETAILS
Needs Votes
Ideas Administrator

Thank you for this suggestion! Currently this is not on our roadmap. We are tracking this idea and if it gathers more votes and comments we will consider it in the future. Best regards, Business Central Team

Comments

D

Not sure why we have to vote to get a bug fixed.

Category: Development