Flow Execution
Summary
This document describes how a Velox Flow executes in the current Velox source code. In the code, Flows are still implemented as TvxActionMan modules and many classes, database columns, comments, and log messages still use the older term "Action". This document uses Flow for the product concept and identifies the source classes that still use Action naming.
Flow execution is centered on TvxActionMan.Execute and TvxActionMan.ExecuteOnce. A Flow is loaded from the Velox configuration database, executed on a trigger-specific thread, runs its active steps in order, commits or rolls back data work, moves files when applicable, saves logs according to configured status filters, sends optional notifications, and may trigger linked Flows after success.
The Velox source code is the authority for this document. Where behavior could not be determined from source inspection, it is marked as unclear.
Related PKB Documents
- ARCHITECTURE.md
- DOMAIN_MODEL.md
- MODULE_LIBRARY.md
- SERVICE_REFERENCE.md
- TECHNICAL_DEBT.md
- DATA_FORMAT_REFERENCE.md
- Flow Configuration
- Transport Configuration
- System Runtime Configuration
Source Code Locations
| Area | Source |
|---|---|
| Flow module class and execution loop | Classes\vxActionMan.pas:299, Classes\vxActionMan.pas:1924, Classes\vxActionMan.pas:1994 |
| Flow step classes | Classes\vxActionMan.pas:70, Classes\vxActionMan.pas:92, Classes\vxActionMan.pas:155, Classes\vxActionMan.pas:175, Classes\vxActionMan.pas:208, Classes\vxActionMan.pas:230, Classes\vxActionMan.pas:262, Classes\vxActionMan.pas:278 |
| Flow persistence/configuration fields | Classes\vxActionMan.pas:2717, Classes\vxActionMan.pas:2773 |
| Flow pool/cache | Classes\vxActionPool.pas:85, Classes\vxActionPool.pas:227, Classes\vxActionPool.pas:320, Classes\vxActionPool.pas:377 |
| Manual execution helper | Classes\GUI\vxActionExe.pas, Classes\Service\vxManagerExecution.pas:573, Classes\Service\vxManagerExecution.pas:588 |
| Runtime action threads | Classes\Service\vxActionThread.pas:162, Classes\Service\vxActionThread.pas:276, Classes\Service\vxActionThread.pas:303, Classes\Service\vxActionThread.pas:332, Classes\Service\vxActionThread.pas:626 |
| Schedule manager | Classes\Service\vxManagerScheduler.pas:179, Classes\Service\vxManagerScheduler.pas:210, Classes\Service\vxManagerScheduler.pas:223, Classes\Service\vxManagerScheduler.pas:443, Classes\Service\vxManagerScheduler.pas:567, Classes\Service\vxManagerScheduler.pas:622 |
| Folder monitor manager | Classes\Service\vxManagerMonitor.pas:142, Classes\Service\vxManagerMonitor.pas:257, Classes\Service\vxManagerMonitor.pas:484, Classes\Service\vxManagerMonitor.pas:636, Classes\Service\vxManagerMonitor.pas:643 |
| REST/API manager | Classes\Service\vxManagerREST.pas:109, Classes\Service\vxManagerREST.pas:134, Classes\Service\vxManagerREST.pas:194, Classes\Service\vxManagerREST.pas:314, Classes\Service\vxManagerREST.pas:365, Classes\Service\vxManagerREST.pas:561 |
| API WebBroker dispatch | VeloxAPIService\vxWebModule.pas:50, VeloxAPIService\vxWebModule.pas:61 |
| Data definition transactions | Classes\vxDataDef.pas:1547, Classes\vxDataDef.pas:1572, Classes\vxDataDef.pas:1605, Classes\vxDataDef.pas:1632 |
| Database definition execution | Classes\vxDBDef.pas:217, Classes\vxDBDef.pas:248, Classes\vxDBDef.pas:322 |
| File definition execution | Classes\vxFileDef.pas:561, Classes\vxFileDef.pas:596 |
| File move lifecycle | Classes\vxFileCon.pas:612, Classes\vxFileCon.pas:697, Classes\vxFileCon.pas:775 |
| SQL connection transaction wrapper | Classes\vxSQLConnection.pas:340, Classes\vxSQLConnection.pas:350, Classes\vxSQLConnection.pas:360 |
| Log lifecycle and persistence | Classes\vxModule.pas:2327, Classes\vxModule.pas:2360, Classes\vxModule.pas:3049, Classes\vxModule.pas:3070, Classes\vxModule.pas:3078, Classes\vxModule.pas:3154, Classes\vxModule.pas:3391, Classes\vxModule.pas:3403 |
| Outbound transport retry | Classes\Service\vxActionThread.pas:471, Classes\Service\vxActionThread.pas:541, Classes\Service\vxActionThread.pas:544, Classes\vxModule.pas:4610, Classes\Tools\vxConstant.pas:24 |
Important Classes, Forms, Services, And Configuration
Important Classes
| Class | Purpose |
|---|---|
TvxActionMan | Flow module, persisted in VX_ACTION, owns Flow settings, source definitions, step list, linked Flows, log settings, retry settings, REST settings, and the execution loop. |
TvxActionItem | Base class for Flow steps. The base Execute returns False; concrete descendants implement step behavior. |
TvxActionMap | Executes a configured Map between source and destination data definitions. |
TvxActionReport | Executes a configured Report. |
TvxActionTransport | Registers outbound transport work against Flow logs; actual outbound sending is handled later by the outbound transport manager. TvxActionAPI is a source-visible subclass that defaults to TvxTransportHTTPOut, but no current class registration or main Designer creation path was confirmed. |
TvxActionSQL | Executes custom SQL against a configured DB Definition. |
TvxActionFileRouter | Routes a source file to a destination file connection according to route formulas. |
TvxActionShellExecute | Executes an external command line or shell command. |
TvxActionSubAction | Executes another Flow as a sub-action. |
TvxActionCustomScript | Executes user script logic against a source data definition. |
TvxActionPool / TvxActionPoolItem | Maintains cached loaded TvxActionMan instances by Flow FID. |
TActionThread | Base service/manual thread that gets a Flow from the pool and executes it. |
TManualActionThread | Manual Designer execution thread. |
TScheduleActionThread | Scheduled Flow execution thread. |
TMonitorActionThread | Folder monitor Flow execution thread. |
TRESTActionThread | API service execution thread for REST Flow requests. |
TvxScheduleManager / TvxScheduleItem | Synchronizes and schedules active scheduled Flows. |
TvxMonitorManager / TvxMonitorItem / TvxMonitorFileQueue | Synchronizes monitored Flows and queues detected files. |
TvxRESTManager / TvxRESTItem | Synchronizes REST Flows and maps HTTP endpoints to Flow execution. |
TvxDataDef, TvxDBDef, TvxFileDef | Data source/destination definitions opened and finalized by Flow steps. |
TvxLog, TvxLogFile, TvxLogTransport | Runtime log, file log, and transport log persistence. |
Important Forms
| Form | Purpose |
|---|---|
Forms\frmSetupActions.pas | Flow setup UI, including execution mode, schedule, monitor, REST, retry, logging, and step configuration fields. |
Forms\LinkedAction\frmSetupActions.pas | Ignored by repository guidance as trial/test/backup code; not treated as active flow setup source. |
Forms\frmLogs.pas | Log display used during manual execution. The source location is inferred from calls in Classes\GUI\vxActionExe.pas; exact behavior of the form was not re-audited for this document. |
Forms\frmViewProcesses.pas | Service process/monitoring UI referenced by service documentation; exact Flow stop behavior is partly unclear because schedule EndTask is TODO in source. |
Important Services
| Service | Flow role |
|---|---|
VeloxService | Runs scheduled Flows, monitored folder Flows, inbound transport checking, and outbound transport sending. |
VeloxAPIService | Runs REST/API Flows through WebBroker/Indy and TvxRESTManager. |
Related Configuration
| Setting area | Source-backed behavior |
|---|---|
| Flow execution mode | Stored in VX_ACTION.EXECUTION; loaded into TvxActionMan.ScheduleType; used by managers to decide whether a Flow is manual, scheduled, monitored, REST, or linked. |
| Schedule settings | Stored by TvxActionMan.BeforeSaveModuleEvent; copied into TvxScheduleItem by TvxScheduleManager.SyncAction. |
| Monitor settings | File monitor FID/path and transport monitor settings are copied into monitor execution items by TvxMonitorManager.SyncAction. |
| REST settings | REST method, endpoint, groups, summary, documentation, description, result codes, and anonymous flag are stored by TvxActionMan.BeforeSaveModuleEvent; endpoint lookup is managed by TvxRESTManager. |
| Logging settings | SaveLogStatuses, SendLogStatuses, AdminEmail, NotifyEmail, LogHTTPComms, and LogTransportComms are copied from Flow config into schedule, monitor, REST, and transport execution items. |
| Thread limit | MaxThreadsPerAction creates a per-execution-item semaphore in TvxExecutionItem.SetMaxThreadsPerAction. REST sync sets this property but the source comment states it is ignored for REST. |
| General setup runtime flags | gSetup.ReloadModuleOnError, gSetup.CacheManualActions, service state, API URL/domain/port, email settings, and transport retry polling settings affect execution around the Flow core. |
Terminology
- Flow is the product concept currently represented by
TvxActionMan. - Action is the legacy implementation term still used in class names, database table names, properties, menus, and log text.
- Step means a
TvxActionItemchild of a Flow. Steps execute sequentially inside one Flow execution attempt. - Source Manager means the
TvxDefManagerowned by a Flow. It stores the data definitions used by the Flow. - Sub-action means one Flow running another Flow inside the parent Flow execution.
- Linked Flow means a Flow configured with execution type
fstLinkedActionandLINKEDACTIONFIDpointing to a parent Flow. Linked Flows execute after the parent succeeds.
High-Level Execution Architecture
Loading
Flow Module Loading
TvxActionMan is a TvxModule descendant. It is persisted as a Flow/Action module and loads from the same module infrastructure used by other Velox objects. The primary table named in the class is VX_ACTION, and the constructor sets ModuleDescription to Flow.
TvxActionMan.BeforeSaveModuleEvent writes execution-related fields into the module SQL, including execution type, monitor FID/path, schedule timings, REST metadata, REST result codes, linked action FID/order, and execution description. TvxActionMan.ValidateSave currently returns True with no additional core validation.
Source-backed defaults in TvxActionMan.New include:
- Schedule type defaults to
fstNone. - Repeat interval defaults to
10minutes. RunOnceImmediatelydefaults toFalse.MaxThreadsPerActiondefaults to1.IgnoreCancel,ReprocessUntilError, andAutoRetrydefault toFalse.- Auto retry defaults are count
3and wait5seconds. - REST defaults are method
GET, success200, client error400, server error500, and anonymous accessFalse. - Default saved log statuses are OK, Warning, Issue, Duplicate, and Error; Cancelled is not saved by default.
- Default notification statuses are Warning, Issue, Duplicate, and Error.
Action Pool Loading
Most runtime entry points do not directly create a Flow instance for each run. They call gActionPool.GetAction(FID).
TvxActionPool.GetAction locates or creates a TvxActionPoolItem for the Flow FID. TvxActionPoolItem.GetAction pops an existing cached TvxActionMan instance from the item list if one is available. If none is available, it creates a new TvxActionMan, assigns its pool owner, calls LoadModule(FFID, EmptyGuid), and returns the loaded instance.
After execution:
- Non-manual service threads release the Flow back to the pool unless
ReloadModuleOnErroris enabled and the Flow failed. - Manual execution releases or frees the Flow when the manual log/test thread is closed, depending on
gSetup.CacheManualActions. - REST execution releases the Flow in the REST item after the worker thread completes; if the REST thread times out, the code frees
lThread.Actionin the waiting thread path. - The cleanup thread frees pooled Flow instances whose last access is older than
ACTION_CLEANUP_DELAYminutes. The cleanup thread checks every 25 minutes.
Service Manager Loading
Managers synchronize from VX_ACTION rather than executing all loaded modules:
TvxScheduleManager.Synchroniseselects active, non-archived Flows whereEXECUTION = Ord(fstSchedule).TvxRESTManager.Synchroniseselects active, non-archived Flows whereEXECUTION = Ord(fstREST).TvxMonitorManager.SyncActionloads a Flow and creates or updates a monitor item. The exact SQL select for monitor synchronization was not fully re-read for this document, but the sync path and monitor item behavior were verified in source.
Each manager creates a temporary TvxActionMan, calls LoadModule, copies the required runtime settings into a lightweight execution item, enables that item, then frees the temporary Flow.
Step Module Loading
Steps often lazy-load referenced modules at execution time:
| Step | Lazy-loaded module behavior |
|---|---|
| Map | Loads a TvxMap and assigns its source/destination definitions. |
| Report | Loads a TvxReport and assigns report output settings. |
| Transport | Loads an outbound TvxTransport and assigns action/log context. |
| Sub-action | Loads a target TvxActionMan and runs it as a sub-action. |
| Custom Script | Ensures a TvxScriptItem exists and executes it with the configured source. |
| SQL | Uses the configured DB definition and its DB connection; no separate SQL script module is loaded in the observed TvxActionSQL.Execute path. |
| File Router | Uses route items and file connection configuration owned by the step. |
| Shell Execute | Uses command settings on the step. |
Validation
The core TvxActionMan.ValidateSave method returns True; no core Flow-level save validation is implemented there. Runtime validation occurs inside individual step Execute methods and service manager sync methods.
Examples verified in source:
- Map steps cancel when source or destination data definitions are missing.
- Report steps cancel when the source data definition is missing.
- Transport steps cancel when the outbound transport or source file definition is missing.
- SQL steps cancel when the SQL command is blank or no DB Definition is assigned.
- File Router steps cancel when no File Definition is assigned.
- Sub-action steps log errors when the target Flow is missing or cannot load.
- Custom script steps cancel or warn when no Data Definition is assigned.
- REST endpoint sync checks that the Flow loads and is active before creating/updating the endpoint item.
- Schedule sync checks that the Flow loads and is active before creating/updating the schedule item.
It is unclear whether additional UI validation in Forms\frmSetupActions.pas prevents all invalid combinations before save. This document only confirms the core/runtime behavior above.
Startup By Trigger
Manual Designer Execution
Manual execution is initiated through Classes\GUI\vxActionExe.pas.
The helper creates a TvxManualExecutionItem, opens a log form, creates a TManualActionThread, attaches the Flow log to the visible log form through OnLoadModule, and starts the thread. Manual execution can run in live mode or test mode.
Manual threads wait up to one hour on the per-Flow semaphore before executing. Manual threads are not FreeOnTerminate; they are cleaned up through TvxManualExecutionItem.FreeTestThread.
Scheduled Service Execution
TvxScheduleManager.Synchronise builds schedule items for active scheduled Flows. TvxScheduleItem.Enable optionally runs once immediately, sets start and repeat timers, and enables the start timer.
When a schedule timer fires:
TvxCustomScheduleItem.StartTimerOnExecuteorRepeatTimerOnExecuteruns in a timer thread.ExecuteActionrecords the last run time and callsCreateExecutionThread.- The created
TScheduleActionThreadwaits onMaxThreadsPerActionfor up to one hour. - If it obtains the semaphore, it removes itself from the waiting monitor and calls the base
TActionThread.Execute.
Monitored Folder Execution
TvxMonitorItem.Enable prepares a monitored Flow by creating/starting a monitor queue, processing existing files, creating a TDirectoryWatch, and starting the directory monitor.
When a file is detected:
- The monitor item adds the file name to
TvxMonitorFileQueue. - The queue waits on the per-Flow semaphore for up to one hour.
- It pops a file name from its thread-safe string list.
- It starts a
TMonitorActionThreadfor that file. TMonitorActionThreadsetsFFilePathto the monitor directory plus file name, then calls the base action execution path.- Base execution assigns the path to
FAction.SourceManager.FilePathbefore running the Flow.
The queue source uses Pop, described in code as "get last item and remove from list"; therefore the exact ordering is list-pop behavior, not a documented FIFO guarantee.
REST/API Execution
VeloxAPIService\vxWebModule.pas dispatches requests to gRESTManager.ExecuteAPIForEndpoint.
TvxRESTManager.ExecuteAPIForEndpoint handles:
/by rendering a simple HTML list of active API Flows./favicon.icoby returning an icon resource.- Other paths by looking up
Request.InternalPathInfoinFEndpoints.
TvxRESTItem.WebActionHandler only dispatches GET and POST in the observed source. Other HTTP methods are not handled in that case statement.
For GET and POST:
TvxRESTItemcreates aTRESTActionThread.- The request and response are cast to
TvxAPIRequestandTvxAPIResponse. TRESTActionThread.SetResponsecreates a responseTMemoryStream.- The REST item starts the thread and waits up to five minutes.
- The thread gets the Flow from
gActionPool, setsREST := True, copies query fields into Flow locals, setsVeloxUserNumfrom theX-UserNumheader, assigns request/response objects, and callsFAction.Execute. - On completion, the REST item maps
lAction.Log.LastStatusTypeto HTTP status codes.
Important REST status behavior:
- For GET, only
flsErrormaps to the configured client error status. Issues are treated like success in the observed source because theflsIssuecase is commented out. - For POST, both
flsIssueandflsErrormap to the configured client error status. - If the worker thread has a fatal exception, the response uses the Flow's configured server error status when a Flow is available, otherwise
500. - If the wait times out, the response status is
500with a timeout reason string. - REST sync sets
MaxThreadsPerAction, but the source comment says the semaphore exists and is ignored for REST;TRESTActionThread.Executedoes not wait on the per-Flow semaphore.
Linked Flow Execution
TvxActionMan.LoadLinkedActions loads active, non-archived Flows where EXECUTION = 4 and LINKEDACTIONFID equals the current Flow FID, ordered by LINKEDACTIONORDER.
After a Flow completes successfully, ExecuteOnce calls ExecuteLinkedAction. Linked Flows execute one at a time through ExecuteFlow. If a linked Flow fails, the linked Flow loop stops and the parent Flow logs a warning.
Sub-action Execution
TvxActionSubAction.Execute loads and executes another TvxActionMan as a sub-action. The sub-action inherits the parent test flag and locals. TvxActionMan.ExecuteFlow also supports sub-action mode and updates the parent ActionTotalStatus when called with aSubAction = True.
Sub-actions do not save the master log directly; ExecuteOnce only calls SaveLog when FSubAction is false.
Incoming Transport Check Before First Service Execution
On first execution in server mode, TvxActionMan.ExecuteOnce calls CheckTransports(False) before running steps. CheckTransports exits early for monitored Flows running in the service. For other service executions, if a file monitor and transports are configured, it loads the monitor file connection and executes each configured incoming transport. If transport checking fails, ExecuteOnce exits before running Flow steps.
Manual users can run transport checks with aSaveLog = True; that path sets log details, saves the log, sends notifications, and finishes the log output.
Core Execution Sequence
ExecuteOnce Detailed Sequence
Step Execution
Within a single ExecuteOnce attempt, steps execute sequentially. The loop condition is:
Log.Statusis true.Log.IsCancelledis false.- The loop index is less than
ActionCount.
Inactive steps are skipped. There is no evidence in TvxActionMan.ExecuteOnce of parallel step execution inside one Flow attempt.
| Step type | Execution behavior |
|---|---|
| Map | Requires source and destination definitions; opens source for read; opens destination; executes TvxMap.Execute; logs exceptions as map errors. |
| Report | Requires a source definition; opens report source for read; configures output and print options; executes report output. REST report execution can write to the API response stream. |
| Shell Execute | Processes tags in command and parameters; supports shell or process execution, optional credentials, optional waiting, exit-code error logging, and post-run delay. |
| Transport | Requires outbound transport and source file definition; loads transport; copies Flow log/email settings; creates log transport events for files. It registers outbound work but does not perform the final outbound send inside the Flow step. |
| SQL | Requires SQL text and DB definition; opens source data; starts a DB transaction; processes tags; logs SQL script; executes SQL. Commit/rollback occurs later in ExecuteOnce. |
| File Router | Requires source file definition; opens source file; compiles/evaluates route formulas; copies the file to the first matching route destination unless running in test mode. |
| Sub-action | Loads and executes another Flow, passing test mode and locals. |
| Custom Script | Requires a data definition; opens source data; executes a TvxScriptItem; logs user-failed script results and script exceptions. |
If IgnoreCancel is enabled, ExecuteOnce clears cancellation after a cancelled step unless no step succeeded. If no configured steps exist, the Flow is logged as cancelled.
Scheduling And Orchestration
REST/API Sequence
Transactions And Persistence
Database Data Definitions
Database transaction handling is distributed:
TvxDataDef.vxStartTransactionstarts transactions on the DB connections associated with a data definition and marks the data definition as transaction-started.TvxDBDef.SaveDatastarts a transaction only when master data exists and then saves master dataviews.TvxActionSQL.Executeexplicitly starts a transaction on the DB definition before running custom SQL.TvxActionMan.ExecuteOncefinalizes all source definitions by callingCommitData(Log.Status).CommitData(True)commits;CommitData(False)rolls back.TvxSQLConnection.VxStartTransactionbegins only if the DB connection is not already in transaction.
System Database Transaction
ExecuteOnce also finalizes SystemDB.SQLD:
- If the Flow status is true, it calls
SystemDB.SQLD.VxCommitTran. - If the Flow status is false, it calls
SystemDB.SQLD.vxRollbackTran.
The source comment mentions vxIssues.SaveIssues and TvxScripter.ExecSQL as possible reasons the system SQLD transaction may be used.
File Persistence
File handling is not transactional in the database sense.
After live execution:
- Successful file-source Flows call
MoveFileToAuditandMoveFileToTransport. The source comment states only one should do anything because settingDoMoveToTransportunsets audit movement. - Failed file-source Flows call
MoveFileToError. - If the Flow is cancelled and marked as deadlocked, file movement is skipped so the file remains available for later processing.
- Transported files are audited by transport code, not by the normal Flow source-file audit loop.
In test mode:
- DB work is rolled back.
- System SQLD is rolled back.
- Files are not moved to audit or error.
- Transports are not sent.
Log Persistence
TvxActionMan.SaveLog calls TvxLog.SaveLog only if the current Log.StatusType is in FSaveLogStatuses or if Log.IsDeadlock is true. TvxLog.SaveLog creates a new log module if FNum = 0; otherwise it saves the existing log module.
TvxLog.CreateLogFileEvent and TvxLog.CreateLogTransportEvent create file and transport log records used later by audit/error/transport flows.
Logging And Completion
Flow logging occurs throughout execution:
- Non-sub-action Flow execution sets
Log.Running := Trueat the start ofExecute. ExecuteOncesets action details on the log withSetActionDetailsToLog(fltAction).- Each step logs a start banner and a finished/error line.
- Final completion is logged according to the final
Log.StatusType: OK, Warning, Issue, Duplicate, Cancelled, or Error. Executealways callsLog.DoLogFinishedfor non-sub-actions in itsfinallyblock.- Reprocess-until-error mode also calls
DoLogFinishedbetween iterations; Designer waits up to ten seconds for the log output finished event before starting another iteration. - REST execution calls
TvxLog.GetLogAPIResponseafterSaveLogif the Flow failed. That method writes a problem-details-style JSON response containing errors from the log and sets content typeapplication/problem+json. SendLogNotificationsends email only for statuses inFSendLogStatuses.
TvxLog.SetStatusType only updates the status when the new status is greater than the current status. This means more severe statuses dominate less severe statuses during a run.
Threading And Concurrency
Thread Ownership
Non-REST Flow threads use TActionThread.Execute:
- Add the thread to
gExecutionMonitor. - Call
CoInitializeEx(nil, COINIT_MULTITHREADED). - Get the Flow from
gActionPool. - Attach manual logs for manual execution.
- Assign a monitor file path when present.
- Run
CheckTransports(True)for manual transport-check threads, otherwise runFAction.Execute. - Release SQL and system connection pools for the current thread.
- Release or free the Flow.
- Call
CoUninitialize. - Remove the thread from
gExecutionMonitor.
REST Flow threads use a separate TRESTActionThread.Execute path with similar COM and connection-pool cleanup but with REST-specific request/response setup and no per-Flow semaphore wait.
Per-Flow Thread Limits
TvxExecutionItem.SetMaxThreadsPerAction creates a Windows semaphore with initial and maximum count equal to MaxThreadsPerAction. If the configured value is less than or equal to zero, it is forced to 1.
The following threads wait on this semaphore:
TManualActionThreadTScheduleActionThreadTvxMonitorFileQueuebefore startingTMonitorActionThread- Transport in/out worker paths
The wait timeout is one hour (ONE_HOUR_MILLI). If the wait times out, the thread exits without running the Flow.
Action Pool Safety
gActionPool and TvxActionPoolItem use thread-list locking. An action is popped from the pool while it is in use, then either released back to the pool or freed. This prevents another thread from using the same TvxActionMan instance concurrently through the pool.
Thread Safety Notes From Source
Several source comments explicitly call out thread-safety decisions:
TvxExecutionItemlocks getters because managers can synchronize while action threads are reading execution item state.TvxExecutionItem.ActionandTransportcomments state they must only be called within action/transport threads so they get their own system connection.TActionThread.Executecomments state database connections must be released before freeing modules.TvxTransportQueueItemis created without an owner for thread safety.- REST endpoint lookup locks the dictionary for lookup, then runs the endpoint handler outside the lock so API calls are not serialized by the dictionary lock.
Errors And Cancellation
Errors are recorded through TvxLog and usually affect Log.Status / Log.StatusType.
Observed behavior:
- Step-level configuration errors generally log
Cancelledwhen a required configuration object is missing. - Step-level exceptions are caught in each step and logged as errors.
TvxActionMan.Executecatches unexpected critical Flow exceptions and logs an error.TActionThread.ExecuteandTRESTActionThread.Executecatch unexpected thread-level exceptions and log them to the Windows event logger; background mode calls madExcept handling.- If
gSetup.ReloadModuleOnErroris enabled and a non-manual service Flow fails, the Flow instance is freed instead of returned to the pool. - If a Flow has no steps, it is logged as cancelled.
IgnoreCancelcan clear cancellation after a cancelled step if another step succeeded. If no step succeeded, cancellation is restored.- In reprocess-until-error mode, the loop stops on Duplicate, Cancelled, or Error status.
It is unclear whether all user-driven cancellations from the UI propagate through a single cancellation mechanism. The core log cancellation flags and thread termination paths are visible, but the full UI cancellation workflow was not exhaustively traced for this document.
Retries
Flow Auto-Retry
TvxActionMan.ExecuteOnce implements Flow auto-retry around the whole step loop and finalization path.
When:
Log.Statusis false,FAutoRetryis true,- and the retry count is less than
FAutoRetryCount,
the Flow logs a highlighted retry message, sleeps for FAutoRetryWaitSeconds * 1000, calls Log.ResetStatusToSuccess, and repeats the execution attempt. Defaults in TvxActionMan.New are auto-retry disabled, retry count 3, and wait 5 seconds.
The retry occurs after the previous attempt has already closed/reset data definitions and committed or rolled back according to that attempt's status.
Reprocess Until Error/Cancelled
TvxActionMan.Execute supports a separate reprocess loop controlled by FReprocessUntilError.
DoReprocessUntilError returns true only when:
- Reprocess-until-error is enabled.
- The Flow is not REST.
- The Flow is not in test mode.
- The schedule type is manual (
fstNone), scheduled (fstSchedule), or monitored in Designer (fstMonitorandIsDesigner).
The loop runs ExecuteOnce repeatedly until the log status is Duplicate, Cancelled, or Error. A local loop valve of 1000 exists in the source. The log message says to adjust the setting in General Setup, but this document did not find a General Setup value read by this code path; the loop valve is local in TvxActionMan.Execute.
Outbound Transport Retry
Outbound transport retry is separate from Flow auto-retry.
The Transport step creates TvxLogTransport records. The outbound transport manager later loads unsent transport log records and runs TTransportOutActionThread. During outbound send execution:
TvxLogTransport.IncrementAttemptsincrements attempts and sets status to failed when attempts equalTransportMaxAttempts.LastAttemptDateis set to now.NextAttemptDateis set to now plusMINS_BETWEEN_ATTEMPTS ^ (Attempts + 1)minutes.MINS_BETWEEN_ATTEMPTSis2.- The outbound transport manager polling interval uses
gSetup.TransportAttemptIntervalseconds.
This retry mechanism retries outbound sending, not the original Flow execution.
Completion Lifecycle
A non-sub-action Flow execution completes in this order:
- Step loop finishes, cancels, errors, or exits because no steps remain.
- Data definitions are committed or rolled back.
- System SQLD is committed or rolled back.
- File source movement occurs for audit, transport staging, or error.
- Data definitions are closed and reset.
- Auto-retry may repeat the attempt if configured and the attempt failed.
- Final completion status is logged.
- Master log is saved if the status is configured for saving or deadlock is set.
- REST error response content is written when applicable.
- Log notification email is sent if the status is configured for notification.
- Linked Flows execute only if the parent Flow status is successful.
- Service/non-designer/non-reprocess executions reset the Flow before returning it to the pool.
Executemarks the log no longer running and firesDoLogFinished.- The owning thread releases connection pools and returns/frees the Flow.
Dependency Graph
Behavior Not Determined From Source Review
- The complete Designer menu path for every manual Flow execution command was not re-read for this document. Manual execution behavior was traced from
Classes\GUI\vxActionExe.pas. - The full UI validation matrix in
Forms\frmSetupActions.paswas not exhaustively traced. Runtime validation inTvxActionManand step classes is documented above. - Service process shutdown and force termination behavior is documented in SERVICE_REFERENCE.md; this document only covers Flow execution effects visible in execution classes.
TvxScheduleManager.EndTaskcontains a TODO/commented path. Exact scheduled Flow end-task behavior is therefore unclear from the current source.- The exact monitor synchronization SQL statement was not included in this document, although monitor item enablement, file queue behavior, and action-thread execution were traced.
Questions For Future Review
- Should
TvxActionMan.ValidateSaveenforce required execution-mode fields, or is all validation intentionally UI/runtime-only? - Should REST GET treat
flsIssueas a client error like REST POST, or is the current difference intentional? - Should REST execution honor
MaxThreadsPerAction, since sync creates the semaphore but comments say it is ignored? - Should the reprocess-until-error loop valve be configurable, as the log message implies?
- Should monitor queue ordering be FIFO if file order matters, or is current pop behavior acceptable?
- Should outbound transport retry settings be documented in the Flow UI, since transport retry happens after Flow execution and not as Flow auto-retry?