( id: string, owner: string, input: UpdateProgressInput, )
| 149 | } |
| 150 | |
| 151 | export async function updateRun( |
| 152 | id: string, |
| 153 | owner: string, |
| 154 | input: UpdateProgressInput, |
| 155 | ): Promise<AgentRun | null> { |
| 156 | await ensureTable(); |
| 157 | const client = getDbExec(); |
| 158 | // Read current row first so we can return a consistent snapshot of this |
| 159 | // caller's update (avoids the UPDATE→SELECT race where a concurrent writer |
| 160 | // could have their change reflected in the returned value). |
| 161 | const current = await getRun(id, owner); |
| 162 | if (!current) return null; |
| 163 | |
| 164 | const now = Date.now(); |
| 165 | const sets: string[] = ["updated_at = ?"]; |
| 166 | const args: Array<string | number | null> = [now]; |
| 167 | const next: AgentRun = { |
| 168 | ...current, |
| 169 | updatedAt: new Date(now).toISOString(), |
| 170 | }; |
| 171 | |
| 172 | if (Object.prototype.hasOwnProperty.call(input, "percent")) { |
| 173 | const percent = input.percent == null ? null : clampPercent(input.percent); |
| 174 | sets.push("percent = ?"); |
| 175 | args.push(percent); |
| 176 | next.percent = percent; |
| 177 | } |
| 178 | if (input.step !== undefined) { |
| 179 | sets.push("step = ?"); |
| 180 | args.push(input.step); |
| 181 | next.step = input.step; |
| 182 | } |
| 183 | if (input.metadata !== undefined) { |
| 184 | sets.push("metadata = ?"); |
| 185 | args.push(JSON.stringify(input.metadata)); |
| 186 | next.metadata = input.metadata; |
| 187 | } |
| 188 | if (input.status !== undefined) { |
| 189 | sets.push("status = ?"); |
| 190 | args.push(input.status); |
| 191 | next.status = input.status; |
| 192 | if (input.status !== "running") { |
| 193 | sets.push("completed_at = ?"); |
| 194 | args.push(now); |
| 195 | next.completedAt = new Date(now).toISOString(); |
| 196 | } |
| 197 | } |
| 198 | args.push(id, owner); |
| 199 | |
| 200 | await client.execute({ |
| 201 | sql: `UPDATE progress_runs SET ${sets.join(", ")} WHERE id = ? AND owner = ?`, |
| 202 | args, |
| 203 | }); |
| 204 | bumpPoll(owner); |
| 205 | return next; |
| 206 | } |
| 207 | |
| 208 | function clampPercent(n: number): number { |
no test coverage detected