status-and-callbacks.md 3.7 KB

Status And Callbacks

Forge business workflow status must be maintained by the business module, not inferred only from Flowable screens.

Recommended Status Set

Use these values unless the domain has a strong reason to extend them:

Status Meaning Typical allowed actions
DRAFT Created but not submitted edit, delete, submit
IN_PROCESS Flow instance is running in approval nodes view, save allowed node fields
NEED_MODIFY Rejected back to applicant modify node edit permitted fields, resubmit, terminate
APPROVED Flow completed successfully readonly, domain side effects
REJECTED Applicant terminated or flow rejected readonly/delete depending on domain
CANCELED Flow canceled/withdrawn/terminated readonly/delete depending on domain

Business Table Fields

Add at least:

`status` varchar(32) NOT NULL DEFAULT 'DRAFT' COMMENT '业务状态',
`business_key` varchar(128) DEFAULT NULL COMMENT '流程业务Key',
`process_instance_id` varchar(128) DEFAULT NULL COMMENT '流程实例ID'

Add per-node approver and remark fields only when the business table must retain them for search/reporting. Otherwise task comments can stay in flow task history.

Callback Contract

Code-first Services should use:

@FlowBind(modelKey = MODEL_KEY, businessType = BUSINESS_TYPE)
public class XxxServiceImpl {

    @FlowCallback(on = {
            FlowCallback.ON_TASK_CREATED,
            FlowCallback.ON_TASK_COMPLETED,
            FlowCallback.ON_COMPLETED,
            FlowCallback.ON_REJECTED,
            FlowCallback.ON_CANCELED
    })
    @Transactional(rollbackFor = Exception.class)
    public void handleFlowEvent(FlowEventContext context) {
        // load by tenant + businessKey; update idempotently
    }
}

Required handling:

  • ON_TASK_CREATED: repair business status from current active node. This is critical for reject-to-modify flows.
  • ON_TASK_COMPLETED: copy task variables needed by the business and move status for reject/resubmit decisions.
  • ON_COMPLETED: set approved and copy final variables, but do not assume this event is the only reliable source.
  • ON_REJECTED: set rejected with reason.
  • ON_CANCELED: set canceled with reason.

Repair Rules

Do not trust event ordering as the only source of truth. Add repair at three points:

  1. TASK_CREATED callback:

    • Applicant modify node: IN_PROCESS -> NEED_MODIFY.
    • Approval node: NEED_MODIFY -> IN_PROCESS.
  2. Task form save:

    • If applicant modify save sees IN_PROCESS, repair to NEED_MODIFY before validation.
    • If approval save sees NEED_MODIFY, repair to IN_PROCESS before validation.
  3. Page/detail query:

    • For running statuses, query active sys_flow_task by business_key.
    • Map active task_def_key back to expected business status.
    • Persist and return repaired status when drift is found.

Variable Safety

  • Write approval variables before completing the task so gateways and callbacks can read them.
  • Merge runtime variables and historic variables for terminal events when implementing flow side logic.
  • Business callback must be idempotent and tolerate missing variables.
  • Keep recordId, businessKey, and user IDs as strings in frontend. Do not convert Snowflake IDs to JS Number.

Idempotency

  • Flow start must be guarded by tenantId + businessKey.
  • Low-code platform start already uses locks and ai_business_flow_instance_link; do not add duplicate frontend start paths.
  • Code-first business Services should prevent double submit by checking status and existing business_key/process_instance_id.
  • Domain side effects after approval must have their own idempotency key.