Skip to content

Conversation

cstockton
Copy link
Contributor

@cstockton cstockton commented Aug 22, 2025

Summary

Introduce a new apitask package for running background tasks within the lifecycle of an API request. We then use this feature in the mailer client to send emails in the background. Before the request returns to the caller we first wait for all in-flight tasks to exit.

Summary:

  • Define a Task interface for light background work.
  • Add Run(ctx, task) to schedule tasks asynchronously when supported, or fall back to synchronous execution otherwise.
  • Add Wait(ctx) to block until all request-scoped tasks finish
  • Add Middleware to wrap HTTP handlers, attaching a request-scoped worker to the context and ensuring all tasks complete before returning a response.
  • Add a check for EmailBackgroundSending in mailer package, when present wrap the mail client in a backgroundMailClient. When Mail is called it will send a mailer.Task to apitasks.Run to send the email in the background using the wrapped MailClient.
  • Add config GOTRUE_MAILER_EMAIL_BACKGROUND_SENDING (def false) - on/off switch.

I will follow up with unit tests once the team has had an opportunity to review.

Done: #2146

* Add background worker disabled by default (`GOTRUE_WORKER_ENABLED`)
* Worker pool runs N workers (`runtime.NumCPU() * GOTRUE_WORKER_COUNT_PER_CPU`)
* Graceful shutdown drains tasks during `GOTRUE_WORKER_SHUTDOWN_DURATION`
* Enqueue slow I/O (initially mail) instead of blocking inside transactions
@coveralls
Copy link

coveralls commented Aug 22, 2025

Pull Request Test Coverage Report for Build 17275121624

Details

  • 63 of 155 (40.65%) changed or added relevant lines in 6 files are covered.
  • 2 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.2%) to 70.588%

Changes Missing Coverage Covered Lines Changed/Added Lines %
internal/api/options.go 0 1 0.0%
internal/api/api.go 6 8 75.0%
internal/mailer/noop.go 1 5 20.0%
internal/api/apitask/apitask.go 36 61 59.02%
internal/mailer/mailer.go 16 76 21.05%
Files with Coverage Reduction New Missed Lines %
internal/mailer/mailer.go 2 36.63%
Totals Coverage Status
Change from base Build 17273411118: -0.2%
Covered Lines: 12348
Relevant Lines: 17493

💛 - Coveralls

Copy link
Contributor

@hf hf left a comment

Choose a reason for hiding this comment

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

Looks good!

@cstockton cstockton marked this pull request as ready for review August 23, 2025 18:22
@cstockton cstockton requested a review from a team as a code owner August 23, 2025 18:22
Chris Stockton added 2 commits August 23, 2025 11:49
Introduce a new `apitask` package for running background tasks within the
lifecycle of an API request. We then use this feature in the mailer client to
send emails in the background when `GOTRUE_MAILER_EMAIL_BACKGROUND_SENDING`
is set to true. Before the request returns to the caller we first wait for all
in-flight tasks to exit. This is the smallest possible step I could come up with
to remove blocking email sending calls from the request path.

Summary:
* Define a `Task` interface for light background work.
* Add `Run(ctx, task)` to schedule tasks asynchronously when supported, or fall
  back to synchronous execution otherwise.
* Add `Wait(ctx)` to block until all request-scoped tasks finish
* Add `Middleware` to wrap HTTP handlers, attaching a request-scoped worker to
  the context and ensuring all tasks complete before returning a response.
* Add a check for `EmailBackgroundSending` in mailer package, when present
  wrap the mail client in a `backgroundMailClient`. When `Mail` is called it
  will send a `mailer.Task` to `apitasks.Run` to send the email in the
  background using the wrapped `MailClient`.
@cstockton cstockton force-pushed the cs/feat-background-workers branch from c8fd310 to 070fa36 Compare August 27, 2025 01:21
@cstockton cstockton changed the title feat: introduce memory backed background workers & async mail sending feat: introduce request-scoped background tasks & async mail sending Aug 27, 2025
@cstockton cstockton requested review from hf and cemalkilic August 27, 2025 01:53
return context.WithValue(ctx, ctxKey, wrk)
}

var ctxKey = new(int)
Copy link
Contributor

Choose a reason for hiding this comment

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

Cool idea!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

@cstockton cstockton merged commit 2c8ea61 into master Aug 27, 2025
5 checks passed
@cstockton cstockton deleted the cs/feat-background-workers branch August 27, 2025 20:15
hf pushed a commit that referenced this pull request Aug 28, 2025
🤖 I have created a release *beep* *boop*
---


##
[2.179.0](v2.178.0...v2.179.0)
(2025-08-28)


### Features

* add oauth2 client support
([#2098](#2098))
([8fae015](8fae015))
* experimental own linking domains per provider
([#2119](#2119))
([747bf3b](747bf3b))
* fetch email from snapchat oauth provider if available for consistency
([#2110](#2110))
([7507822](7507822))
* implement link identity with oidc / native sign in
([#2108](#2108))
([5f0ec87](5f0ec87))
* implements email-less accounts with oauth
([#2105](#2105))
([9a61dae](9a61dae))
* introduce request-scoped background tasks & async mail sending
([#2126](#2126))
([2c8ea61](2c8ea61))
* refactor mailer client wiring and add validation wrapper
([#2130](#2130))
([68c40a6](68c40a6))
* support multiple `aud` for the external providers
([#2117](#2117))
([ca5792e](ca5792e))
* use `slices.Contains` instead of for loops
([#2111](#2111))
([9f22682](9f22682))


### Bug Fixes

* add `id-token` permission to ci
([#2143](#2143))
([79209c0](79209c0))
* add missing param
([#2125](#2125))
([c0b75f6](c0b75f6))
* change s3 artifact upload role
([#2145](#2145))
([767e371](767e371))
* remove requirement of empty content-type on 204
([#2128](#2128))
([ecc97e0](ecc97e0))
* run release-please again
([#2144](#2144))
([2560f14](2560f14))
* stripped binary now includes version
([#2147](#2147))
([609f169](609f169))
* update copyright year in LICENSE
([#2142](#2142))
([67fe0b0](67fe0b0))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

4 participants