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

Allows users to pass in their own Supervisor for async steps #77

Merged
merged 5 commits into from
Sep 20, 2022

Conversation

Adzz
Copy link
Contributor

@Adzz Adzz commented Sep 16, 2022

Imagine an app called Blog that uses Sage.

Currently Sage allows async steps that spin up a task supervised under Sage.AsyncTransactionSupervisor. Because Sage is a dep of Blog, on shutdown Blog will shutdown before Sage does.

That means if an async step interacts with a process under Blog's supervision tree and you are using some sort of rolling deploy you can enter the following scenario:

  1. Blog starts async task
  2. Sage starts doing that task
  3. Blog shuts down
  4. Sage tries to interact with a process in Blog and can't - so it crashes / errors.

Possible Solutions

  1. Make Sage a library and allow users to start it themselves?
  2. Allow the user to pass in their own supervisor under which it can start the async steps.

This PR does 2.

Imagine an app called Blog that uses Sage.

Currently Sage allows async steps that spin up a task supervised under
`Sage.AsyncTransactionSupervisor`. Because Sage is a dep of Blog, on shutdown
Blog will shutdown _before_ Sage does.

That means if an async step interacts with a process under Blog's
supervision tree and you are using some sort of rolling deploy you can
enter the following scenario:

1. Blog starts async task
2. Sage starts doing that task
3. Blog shuts down
4. Sage tries to interact with a process in Blog and can't - so it
   crashes / errors.

Possible Solutions

1. Make Sage a library and allow users to start it themselves?
2. Allow the user to pass in their own supervisor under which it can
   start the async steps.

This PR does 2.
@ulissesalmeida
Copy link
Contributor

ulissesalmeida commented Sep 16, 2022

That's a pretty good idea. We should let caller specify which task supervisor the task should run under.

@AndrewDryga
Copy link
Member

Hello @Adzz, I love the change.

I think the only things left are tests and adding documentation to functions explaining how we can override the default supervisor.

@Adzz
Copy link
Contributor Author

Adzz commented Sep 20, 2022

Great stuff I'll add that now.

@Adzz
Copy link
Contributor Author

Adzz commented Sep 20, 2022

@AndrewDryga I have added a test and some docs, please let me know if you have any suggestions.


# The async task will be awaited as it's the last step in the pipeline meaning
# there's no chance that we reach here _before_ the send has happened (causing a flaky test)
assert_received({^ref, ancestors}, 1_000)
Copy link
Member

Choose a reason for hiding this comment

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

I would keep the default timeout here, if it starts to fail and become flaky, that's either a reason to increase it globally on CI (because of slow VMs) or there is something worth investigating.

I would also remove the comment above, I think await behavior is already explained in docs.

lib/sage.ex Outdated Show resolved Hide resolved
Co-authored-by: Andrew Dryga <andrew@dryga.com>
Comment on lines +392 to +395
* `:supervisor` - the name of a supervisor that the task will be spawned under. Defaults to the\
`Sage.AsyncTransactionSupervisor` started by Sage (meaning it will exist under Sage's supervision\
tree). It might be a good idea to pass your own in to avoid race conditions on shutdown if your\
step interacts with a process in your own app's supervision tree.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* `:supervisor` - the name of a supervisor that the task will be spawned under. Defaults to the\
`Sage.AsyncTransactionSupervisor` started by Sage (meaning it will exist under Sage's supervision\
tree). It might be a good idea to pass your own in to avoid race conditions on shutdown if your\
step interacts with a process in your own app's supervision tree.
* `:supervisor` - the name of a `Task.Supervisor` that the task will be spawned under. Defaults to the\
`Sage.AsyncTransactionSupervisor` started by Sage (meaning it will exist under Sage's supervision\
tree). It might be a good idea to pass your own in to avoid race conditions on shutdown if your\
step interacts with a process in your own app's supervision tree.

@AndrewDryga
Copy link
Member

@Adzz don't worry about docs formatting, LGTM. I'll slightly edit them and release a new version. Thank you ❤️

@AndrewDryga AndrewDryga merged commit 186ece0 into Nebo15:master Sep 20, 2022
@Adzz
Copy link
Contributor Author

Adzz commented Sep 20, 2022

Sounds good thanks for the quick feedback!

@Adzz Adzz deleted the allow_user_supervisor branch October 21, 2022 15:05
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.

3 participants