Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idempotent queue pause and resume #408

Merged
merged 1 commit into from
Jun 29, 2024

Conversation

brandur
Copy link
Contributor

@brandur brandur commented Jun 29, 2024

I was writing tests for River UI and found that when trying to pause an
already paused queue or resume an unpaused queue, River returns a "not
found" error.

This was quite surprising, so much so that it took me a good half hour
of debugging before I considered the fact that it might actually be a
problem in upstream River. Even if an argument were to be made that
pausing an already paused queue should be an error like "queue already
paused", returning "not found" is misleading and guaranteed to result
in confused people beyond just myself.

I think it's fine for pause and resume to be considered idempotent
operations. If a paused queue is paused again, there's no real damage
done, especially if we keep the original paused time, which we do in
this implementation.

Similarly, make an update so that when pausing or resuming using the
all queues string (*), don't return "not found" error if there are no
queues in the database. Instead, just no-op.

@brandur brandur requested a review from bgentry June 29, 2024 16:44
Copy link
Contributor

@bgentry bgentry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion, this definitely should have worked this way from the beginning. Also we probably want a changelog entry.

Comment on lines 56 to 61
UPDATE river_queue
SET
paused_at = now(),
paused_at = coalesce(queue_to_update.paused_at, now()),
updated_at = now()
FROM queue_to_update
WHERE river_queue.name = queue_to_update.name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid editing a row for no reason, we could take an approach we've done in some other queries: do the update in a CTE, and then for the final return do a union w/ the updated row and original row to return only one of them.

Not a high throughput query so it doesn't matter much, but it would be a nice tweak to stay consistent in our approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, good call. Updated.

@brandur brandur force-pushed the brandur-idempotent-pause-or-resume branch from 4beef49 to 7543bbe Compare June 29, 2024 21:41
@brandur
Copy link
Contributor Author

brandur commented Jun 29, 2024

@bgentry Actually, while looking through that query code I found one other related problem: when you pause/resume using the all queues * string and there are no queues in the database, it returns a "not found" error.

This also feels a bit wrong to me, so I changed it to be a no-op. Do you agree with that behavior? If so, maybe take one more review pass since I added some more code and test cases.

@brandur brandur requested a review from bgentry June 29, 2024 21:43
@bgentry
Copy link
Contributor

bgentry commented Jun 29, 2024

Yes, I agree, a no op seems better in that case!

I was writing tests for River UI and found that when trying to pause an
already paused queue or resume an unpaused queue, River returns a "not
found" error.

This was quite surprising, so much so that it took me a good half hour
of debugging before I considered the fact that it might actually be a
problem in upstream River. Even if an argument were to be made that
pausing an already paused queue should be an error like "queue already
paused", returning "not found" is misleading and guaranteed to result
in confused people beyond just myself.

I think it's fine for pause and resume to be considered idempotent
operations. If a paused queue is paused again, there's no real damage
done, especially if we keep the original paused time, which we do in
this implementation.

Similarly, make an update so that when pausing or resuming using  the
all queues string (`*`), don't return "not found" error if there are no
queues in the database. Instead, just no-op.
@brandur brandur force-pushed the brandur-idempotent-pause-or-resume branch from 7543bbe to 52b6144 Compare June 29, 2024 21:51
@brandur
Copy link
Contributor Author

brandur commented Jun 29, 2024

Great, thanks! Also added changelog.

@brandur brandur merged commit 57a6622 into master Jun 29, 2024
10 checks passed
@brandur brandur deleted the brandur-idempotent-pause-or-resume branch June 29, 2024 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants