diff --git a/config/config.go b/config/config.go index b3ac8cbc6..ec851f3fe 100644 --- a/config/config.go +++ b/config/config.go @@ -1,5 +1,6 @@ package config +// Mailroom is the global configuration var Mailroom *Config func init() { @@ -15,15 +16,16 @@ type Config struct { Elastic string `help:"URL for your ElasticSearch service"` Version string `help:"the version of this mailroom install"` LogLevel string `help:"the logging level courier should use"` - SMTPServer string `help:"the smtp configuration for sending emails ex: smtp://user%40password@server:port/?from=foo%40gmail.com"` BatchWorkers int `help:"the number of go routines that will be used to handle batch events"` HandlerWorkers int `help:"the number of go routines that will be used to handle messages"` RetryPendingMessages bool `help:"whether to requeue pending messages older than five minutes to retry"` - MaxValueLength int `help:"the maximum size in characters for contact field values and run result values"` - MaxStepsPerSprint int `help:"the maximum number of steps allowed per engine sprint"` + WebhooksTimeout int `help:"the timeout in seconds for webhook calls from engine"` + SMTPServer string `help:"the smtp configuration for sending emails ex: smtp://user%40password@server:port/?from=foo%40gmail.com"` + MaxStepsPerSprint int `help:"the maximum number of steps allowed per engine sprint"` + MaxValueLength int `help:"the maximum size in characters for contact field values and run result values"` LibratoUsername string `help:"the username that will be used to authenticate to Librato"` LibratoToken string `help:"the token that will be used to authenticate to Librato"` @@ -50,17 +52,19 @@ type Config struct { // NewMailroomConfig returns a new default configuration object func NewMailroomConfig() *Config { return &Config{ - DB: "postgres://temba:temba@localhost/temba?sslmode=disable", - DBPoolSize: 36, - Redis: "redis://localhost:6379/15", - Elastic: "http://localhost:9200", - BatchWorkers: 4, - HandlerWorkers: 32, - LogLevel: "error", - Version: "Dev", + DB: "postgres://temba:temba@localhost/temba?sslmode=disable", + DBPoolSize: 36, + Redis: "redis://localhost:6379/15", + Elastic: "http://localhost:9200", + BatchWorkers: 4, + HandlerWorkers: 32, + LogLevel: "error", + Version: "Dev", + + WebhooksTimeout: 15, SMTPServer: "", - MaxValueLength: 640, MaxStepsPerSprint: 100, + MaxValueLength: 640, S3Endpoint: "https://s3.amazonaws.com", S3Region: "us-east-1", diff --git a/goflow/engine.go b/goflow/engine.go index 177abc2f8..7a79031ca 100644 --- a/goflow/engine.go +++ b/goflow/engine.go @@ -16,27 +16,16 @@ import ( "github.com/shopspring/decimal" ) -var httpClient *http.Client var eng, simulator flows.Engine -var engInit, simulatorInit sync.Once +var engInit, simulatorInit, webhooksHTTPInit sync.Once + +var webhooksHTTPClient *http.Client +var webhooksHTTPRetries *httpx.RetryConfig var emailFactory engine.EmailServiceFactory var classificationFactory engine.ClassificationServiceFactory var airtimeFactory engine.AirtimeServiceFactory -func init() { - // customize the default golang transport - t := http.DefaultTransport.(*http.Transport).Clone() - t.MaxIdleConns = 32 - t.MaxIdleConnsPerHost = 8 - t.IdleConnTimeout = 30 * time.Second - t.TLSClientConfig = &tls.Config{ - Renegotiation: tls.RenegotiateOnceAsClient, // support single TLS renegotiation - } - - httpClient = &http.Client{Transport: t, Timeout: time.Duration(15 * time.Second)} -} - // RegisterEmailServiceFactory can be used by outside callers to register a email factory // for use by the engine func RegisterEmailServiceFactory(factory engine.EmailServiceFactory) { @@ -63,10 +52,10 @@ func Engine() flows.Engine { "X-Mailroom-Mode": "normal", } - retries := httpx.NewRetryDelays(3, 10) + httpClient, httpRetries := webhooksHTTP() eng = engine.NewBuilder(). - WithWebhookServiceFactory(webhooks.NewServiceFactory(httpClient, retries, webhookHeaders, 10000)). + WithWebhookServiceFactory(webhooks.NewServiceFactory(httpClient, httpRetries, webhookHeaders, 10000)). WithEmailServiceFactory(emailFactory). WithClassificationServiceFactory(classificationFactory). WithAirtimeServiceFactory(airtimeFactory). @@ -85,6 +74,8 @@ func Simulator() flows.Engine { "X-Mailroom-Mode": "simulation", } + httpClient, _ := webhooksHTTP() // don't do retries in simulator + simulator = engine.NewBuilder(). WithWebhookServiceFactory(webhooks.NewServiceFactory(httpClient, nil, webhookHeaders, 10000)). WithClassificationServiceFactory(classificationFactory). // simulated sessions do real classification @@ -97,6 +88,27 @@ func Simulator() flows.Engine { return simulator } +func webhooksHTTP() (*http.Client, *httpx.RetryConfig) { + webhooksHTTPInit.Do(func() { + // customize the default golang transport + t := http.DefaultTransport.(*http.Transport).Clone() + t.MaxIdleConns = 32 + t.MaxIdleConnsPerHost = 8 + t.IdleConnTimeout = 30 * time.Second + t.TLSClientConfig = &tls.Config{ + Renegotiation: tls.RenegotiateOnceAsClient, // support single TLS renegotiation + } + + webhooksHTTPClient = &http.Client{ + Transport: t, + Timeout: time.Duration(config.Mailroom.WebhooksTimeout) * time.Second, + } + + webhooksHTTPRetries = httpx.NewRetryDelays(3, 10) + }) + return webhooksHTTPClient, webhooksHTTPRetries +} + func simulatorEmailServiceFactory(session flows.Session) (flows.EmailService, error) { return &simulatorEmailService{}, nil }