-
Notifications
You must be signed in to change notification settings - Fork 694
Description
Describe the issue
When parallel export processing is enabled, it is possible for two background sessions to execute Audit Line Export Runner on the same Audit File Export Line record simultaneously. SAF-T export is an extremely resource-intensive operation — it reads and processes large volumes of financial data, generates XML.
In Audit Line Export Runner I suggest to add after acquiring the lock and before writing session info, check if another active session is already processing this record.
Additionally, I think that the StartExportLinesNotStartedYet should cancel the existing scheduled task before creating a new one for the same line.
Expected behavior
Each Audit File Export Line should be processed by exactly one background session at a time. If a task is already running for a given line, no additional task should be scheduled or started for that same line until the current one completes or fails.
Steps to reproduce
Scenario 1: Error handler reschedules while a new task is already running
Audit File Export Error Handl. unconditionally calls StartExportLinesNotStartedYet after a failure. Combined with the infinite retry issue (where the runner resets "No. Of Attempts" to 3 on every run), this creates overlapping executions:
- Task A (Session 1) is running on Export Line X
- Task A fails → Error Handler sets
Status := Failed, callsStartExportLinesNotStartedYet StartExportLinesNotStartedYetsees Line X withStatus = Failedand"No. Of Attempts" = 2→ schedules Task B- Task B (Session 2) starts executing on Line X
- Meanwhile, another failing line's error handler also calls
StartExportLinesNotStartedYet, which may find Line X again (if Task B hasn't committed its Session ID yet) and schedule Task C - Now Task B and Task C are both processing Line X concurrently
Scenario 2: Race window between task scheduling and session registration
There is a time window between when a task is scheduled via TaskScheduler.CreateTask() and when the runner writes its Session ID to the record via Rec.Modify() + Commit():
StartExportLinesNotStartedYetis called from two different error handler sessions nearly simultaneously- Both read Line X with
Status = Failed(set by a previous error handler) - Both see
"No. Of Attempts" <> 0andStatus <> Completed - For
Status = Failedlines, the code does NOT checkIsExportSessionActive— it goes directly toRunThisLine := true - Both call
RunGenerateAuditFileOnSingleLine, each scheduling a separateTaskScheduler.CreateTask()for the same record - The second
CreateTaskoverwrites the first"Task ID"on the record, but the first task is already scheduled in TaskScheduler and will also run - Two sessions now execute the runner on the same Export Line
Additional context
In environments with multiple BC server instances, the problem becomes even harder to control. The Active Session table only reliably returns sessions for the current server instance.
I will provide a fix for a bug
- I will provide a fix for a bug