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;
.........
Comments
Not sure why we have to vote to get a bug fixed.
Category: Development
Business Central Team (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