( session: GoalQueueSession, work: () => Promise<T>, )
| 174 | } |
| 175 | |
| 176 | async function withQueueMutationLock<T>( |
| 177 | session: GoalQueueSession, |
| 178 | work: () => Promise<T>, |
| 179 | ): Promise<T> { |
| 180 | const filePath = goalQueuePath(session); |
| 181 | const previous = queueMutationLocks.get(filePath) ?? Promise.resolve(); |
| 182 | const run = previous.catch(() => undefined).then(work); |
| 183 | const lock = run.then( |
| 184 | () => undefined, |
| 185 | () => undefined, |
| 186 | ); |
| 187 | queueMutationLocks.set(filePath, lock); |
| 188 | try { |
| 189 | return await run; |
| 190 | } finally { |
| 191 | if (queueMutationLocks.get(filePath) === lock) { |
| 192 | queueMutationLocks.delete(filePath); |
| 193 | } |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | function emptyQueueFile(): GoalQueueFile { |
| 198 | return { version: GOAL_QUEUE_VERSION, goals: [] }; |
no test coverage detected