* @brief Select next available task for processing * * @return Task record or null if no task available * * Selection Logic: * 1. No running tasks (STATUS=1) in system * 2. Task status is NEW(0) or RETRY(-2,-3) * 3. Task not finished and has content * 4. Prioritize NEW tasks over RETRY *
()
| 111 | * @note Ensures single task execution across processes |
| 112 | */ |
| 113 | async function select_task() { |
| 114 | const query_select_task = TASK_QUERIES.SELECT_TASK; |
| 115 | // IMPORTANT!!!! The NOT EXISTS line ensures that even if there are multiple processes, |
| 116 | // only one process is executing at any given time, meaning if a task is in status=1, |
| 117 | // other processes will not proceed to process other tasks with status=0. |
| 118 | // SQL statment: |
| 119 | // WITH T AS ( |
| 120 | // SELECT * |
| 121 | // FROM TASK |
| 122 | // WHERE (STATUS=0 AND PID = ${process.pid}) |
| 123 | // OR STATUS=-2 |
| 124 | // OR STATUS=-3 |
| 125 | // ) |
| 126 | // SELECT TOP 1 * |
| 127 | // FROM T |
| 128 | // WHERE NOT EXISTS (SELECT 1 FROM TASK WHERE STATUS=1) |
| 129 | // AND FINISH_AT IS NULL |
| 130 | // AND FILE_SIZE > 0 |
| 131 | // AND IS_DELETE IS NULL |
| 132 | // ORDER BY |
| 133 | // CASE WHEN STATUS=0 THEN 0 ELSE 1 END, |
| 134 | // CASE WHEN STATUS=0 THEN CREATE_AT END, |
| 135 | // CASE WHEN STATUS=-2 OR STATUS=-3 THEN RETRY END; |
| 136 | // |
| 137 | |
| 138 | try { |
| 139 | const pool = await pool_promise; |
| 140 | const result = await pool.request() |
| 141 | .input('pid', sql.Int, process.pid) |
| 142 | .query(query_select_task); |
| 143 | |
| 144 | // Currently no unexecuted tasks |
| 145 | if (!result.recordset.length) { |
| 146 | return null; |
| 147 | } |
| 148 | |
| 149 | const task = result.recordset[0]; |
| 150 | const memo = operation_memo({ ref: task.OBJID }); |
| 151 | |
| 152 | task.CREATE_AT = new Date(task.CREATE_AT).toISOString(); |
| 153 | |
| 154 | logger(LOG_LEVEL.INFO, `Task ${task.OBJID} selected for execution`, memo); |
| 155 | logger(LOG_LEVEL.INFO_TABLE, task); |
| 156 | |
| 157 | return task; |
| 158 | } catch (err) { |
| 159 | logger(LOG_LEVEL.ERROR, `select_task ${err}.`, operation_memo({})); |
| 160 | |
| 161 | // No need to throw err, just return null or an empty array if preferred |
| 162 | return null; |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | /** |
| 167 | * @brief Cancel a transcription task by ID |
no test coverage detected