diff --git a/apps/server/src/api-data/automation/__tests__/automation.dao.test.ts b/apps/server/src/api-data/automation/__tests__/automation.dao.test.ts index b83c30e64..533354378 100644 --- a/apps/server/src/api-data/automation/__tests__/automation.dao.test.ts +++ b/apps/server/src/api-data/automation/__tests__/automation.dao.test.ts @@ -116,6 +116,14 @@ describe('deleteTrigger()', () => { expect(removed.length).toEqual(1); expect(removed[0].title).not.toEqual('test-osc'); }); + + it('ignores a trigger that is already gone', async () => { + // a client reconciling several triggers must not be stuck because another client + // removed one of them first: the end state it asked for is the one it gets + const before = getAutomationTriggers(); + await expect(deleteTrigger('never-existed')).resolves.toBeUndefined(); + expect(getAutomationTriggers()).toEqual(before); + }); }); describe('addAutomation()', () => { diff --git a/apps/server/src/api-data/automation/automation.dao.ts b/apps/server/src/api-data/automation/automation.dao.ts index d2e39500d..dd2ca31e3 100644 --- a/apps/server/src/api-data/automation/automation.dao.ts +++ b/apps/server/src/api-data/automation/automation.dao.ts @@ -84,15 +84,17 @@ export async function editTrigger(id: string, newTrigger: TriggerDTO): Promise { - let triggers = getAutomationTriggers(); + const triggers = getAutomationTriggers(); const index = triggers.findIndex((trigger) => trigger.id === id); + // ignore request if the trigger does not exist, as deleteAutomation does for the same reason: + // the caller asked for it to be gone and it is, and failing here makes a client that is + // reconciling several triggers unable to finish once another client removed one of them if (index === -1) { - throw new Error(`Automation with id ${id} not found`); + return; } - triggers = deleteAtIndex(index, triggers); - await saveChanges({ triggers }); + await saveChanges({ triggers: deleteAtIndex(index, triggers) }); } /**