Skip to content

Commit c09999a

Browse files
committed
fix: improve http connection pooling for smtp notifications
1 parent 8f78bad commit c09999a

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

cli/exp_scaletest_notifications.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,16 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
142142
triggerTimes[id] = make(chan time.Time, 1)
143143
}
144144

145+
smtpHTTPTransport := &http.Transport{
146+
MaxConnsPerHost: 512,
147+
MaxIdleConnsPerHost: 512,
148+
MaxIdleConns: 2048,
149+
IdleConnTimeout: 60 * time.Second,
150+
}
151+
smtpHTTPClient := &http.Client{
152+
Transport: smtpHTTPTransport,
153+
}
154+
145155
configs := make([]notifications.Config, 0, userCount)
146156
for range templateAdminCount {
147157
config := notifications.Config{
@@ -157,6 +167,7 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
157167
Metrics: metrics,
158168
SMTPApiURL: smtpAPIURL,
159169
SMTPRequestTimeout: smtpRequestTimeout,
170+
SMTPHttpClient: smtpHTTPClient,
160171
}
161172
if err := config.Validate(); err != nil {
162173
return xerrors.Errorf("validate config: %w", err)

scaletest/notifications/config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package notifications
22

33
import (
4+
"net/http"
45
"sync"
56
"time"
67

@@ -40,6 +41,9 @@ type Config struct {
4041

4142
// SMTPRequestTimeout is the timeout for SMTP requests.
4243
SMTPRequestTimeout time.Duration `json:"smtp_request_timeout"`
44+
45+
// SMTPHttpClient is the HTTP client for SMTP requests.
46+
SMTPHttpClient *http.Client `json:"-"`
4347
}
4448

4549
func (c Config) Validate() error {
@@ -68,6 +72,10 @@ func (c Config) Validate() error {
6872
return xerrors.New("smtp_request_timeout must be set if smtp_api_url is set")
6973
}
7074

75+
if c.SMTPApiURL != "" && c.SMTPHttpClient == nil {
76+
return xerrors.New("smtp_http_client must be set if smtp_api_url is set")
77+
}
78+
7179
if c.DialTimeout <= 0 {
7280
return xerrors.New("dial_timeout must be greater than 0")
7381
}

scaletest/notifications/run.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,15 +298,16 @@ func (r *Runner) watchNotificationsSMTP(ctx context.Context, user codersdk.User,
298298
receivedNotifications := make(map[uuid.UUID]struct{})
299299

300300
apiURL := fmt.Sprintf("%s/messages?email=%s", r.cfg.SMTPApiURL, user.Email)
301-
httpClient := &http.Client{
302-
Timeout: r.cfg.SMTPRequestTimeout,
303-
}
301+
httpClient := r.cfg.SMTPHttpClient
304302

305303
const smtpPollInterval = 2 * time.Second
306304
done := xerrors.New("done")
307305

308306
tkr := r.clock.TickerFunc(ctx, smtpPollInterval, func() error {
309-
req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil)
307+
reqCtx, cancel := context.WithTimeout(ctx, r.cfg.SMTPRequestTimeout)
308+
defer cancel()
309+
310+
req, err := http.NewRequestWithContext(reqCtx, http.MethodGet, apiURL, nil)
310311
if err != nil {
311312
logger.Error(ctx, "create SMTP API request", slog.Error(err))
312313
r.cfg.Metrics.AddError("smtp_create_request")
@@ -317,14 +318,16 @@ func (r *Runner) watchNotificationsSMTP(ctx context.Context, user codersdk.User,
317318
if err != nil {
318319
logger.Error(ctx, "poll smtp api for notifications", slog.Error(err))
319320
r.cfg.Metrics.AddError("smtp_poll")
320-
return xerrors.Errorf("poll smtp api: %w", err)
321+
return nil
321322
}
322323

323324
if resp.StatusCode != http.StatusOK {
325+
// discard the response to allow reusing of the connection
326+
_, _ = io.Copy(io.Discard, resp.Body)
324327
_ = resp.Body.Close()
325328
logger.Error(ctx, "smtp api returned non-200 status", slog.F("status", resp.StatusCode))
326329
r.cfg.Metrics.AddError("smtp_bad_status")
327-
return xerrors.Errorf("smtp api returned status %d", resp.StatusCode)
330+
return nil
328331
}
329332

330333
var summaries []smtpmock.EmailSummary

0 commit comments

Comments
 (0)