Skip to content

Commit f38b51f

Browse files
authored
fix: [REL-8483] limit concurrency on the client to address 429/timeouts issue (#338)
* add semaphore to client * pass default concurrency to test client creation * update some usage examples * wrap feature flag calls * fix discrepancy in provider * make generate * wrap all calls in non-test files * revert changes to resetAccessToken * add test * Remove comment * hardcode max concurrency * forgot the plugin provider again
1 parent 53733ee commit f38b51f

File tree

55 files changed

+696
-170
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+696
-170
lines changed

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ resource "launchdarkly_feature_flag" "terraform" {
4444

4545
- `access_token` (String) The [personal access token](https://docs.launchdarkly.com/home/account-security/api-access-tokens#personal-tokens) or [service token](https://docs.launchdarkly.com/home/account-security/api-access-tokens#service-tokens) used to authenticate with LaunchDarkly. You can also set this with the `LAUNCHDARKLY_ACCESS_TOKEN` environment variable. You must provide either `access_token` or `oauth_token`.
4646
- `api_host` (String) The LaunchDarkly host address. If this argument is not specified, the default host address is `https://app.launchdarkly.com`
47-
- `http_timeout` (Number) The HTTP timeout (in seconds) when making API calls to LaunchDarkly.
47+
- `http_timeout` (Number) The HTTP timeout (in seconds) when making API calls to LaunchDarkly. Defaults to 20 seconds.
4848
- `oauth_token` (String) An OAuth V2 token you use to authenticate with LaunchDarkly. You can also set this with the `LAUNCHDARKLY_OAUTH_TOKEN` environment variable. You must provide either `access_token` or `oauth_token`.

go.mod

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ require (
1717
github.com/stretchr/testify v1.9.0
1818
)
1919

20-
require github.com/launchdarkly/api-client-go/v17 v17.1.0
20+
require (
21+
github.com/launchdarkly/api-client-go/v17 v17.1.0
22+
golang.org/x/sync v0.16.0
23+
)
2124

2225
require (
2326
github.com/BurntSushi/toml v1.2.1 // indirect
@@ -31,7 +34,6 @@ require (
3134
github.com/yuin/goldmark v1.7.1 // indirect
3235
github.com/yuin/goldmark-meta v1.1.0 // indirect
3336
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
34-
golang.org/x/sync v0.12.0 // indirect
3537
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
3638
gopkg.in/yaml.v2 v2.4.0 // indirect
3739
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,8 +1044,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
10441044
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
10451045
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
10461046
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1047-
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
1048-
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
1047+
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
1048+
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
10491049
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
10501050
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
10511051
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

launchdarkly/audit_log_subscription_helper.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import (
44
"context"
55
"fmt"
66
"log"
7+
"net/http"
78
"sort"
89
"strconv"
910

1011
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1112
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1213
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
14+
ldapi "github.com/launchdarkly/api-client-go/v17"
1315
strcase "github.com/stoewer/go-strcase"
1416
)
1517

@@ -210,7 +212,13 @@ func auditLogSubscriptionRead(ctx context.Context, d *schema.ResourceData, metaR
210212
}
211213
integrationKey := d.Get(INTEGRATION_KEY).(string)
212214

213-
sub, res, err := client.ld.IntegrationAuditLogSubscriptionsApi.GetSubscriptionByID(client.ctx, integrationKey, id).Execute()
215+
var sub *ldapi.Integration
216+
var res *http.Response
217+
var err error
218+
err = client.withConcurrency(client.ctx, func() error {
219+
sub, res, err = client.ld.IntegrationAuditLogSubscriptionsApi.GetSubscriptionByID(client.ctx, integrationKey, id).Execute()
220+
return err
221+
})
214222

215223
if isStatusNotFound(res) && !isDataSource {
216224
log.Printf("[WARN] failed to find integration with ID %q, removing from state if present", id)

launchdarkly/config.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"strconv"
1111
"time"
1212

13+
"golang.org/x/sync/semaphore"
14+
1315
retryablehttp "github.com/hashicorp/go-retryablehttp"
1416
ldapi "github.com/launchdarkly/api-client-go/v17"
1517
)
@@ -18,10 +20,11 @@ import (
1820
var version = "unreleased"
1921

2022
const (
21-
APIVersion = "20240415"
22-
MAX_RETRIES = 12
23-
RETRY_WAIT_MIN = 200 * time.Millisecond
24-
RETRY_WAIT_MAX = 2000 * time.Millisecond
23+
APIVersion = "20240415"
24+
MAX_RETRIES = 12
25+
RETRY_WAIT_MIN = 200 * time.Millisecond
26+
RETRY_WAIT_MAX = 10000 * time.Millisecond
27+
DEFAULT_MAX_CONCURRENCY = 1 // provider-specific parallelism to avoid hitting rate limits / timeouts
2528
)
2629

2730
// Client is used by the provider to access the ld API.
@@ -36,14 +39,27 @@ type Client struct {
3639
ld404Retry *ldapi.APIClient
3740
ctx context.Context
3841
fallbackClient *http.Client
42+
43+
semaphore *semaphore.Weighted
44+
}
45+
46+
func (c *Client) withConcurrency(ctx context.Context, fn func() error) error {
47+
// this will block if the semaphore has reached its maxConcurrent requests
48+
if err := c.semaphore.Acquire(ctx, 1); err != nil {
49+
return fmt.Errorf("failed to acquire semaphore: %w", err)
50+
}
51+
defer c.semaphore.Release(1)
52+
53+
return fn()
3954
}
4055

41-
func newClient(token string, apiHost string, oauth bool, httpTimeoutSeconds int) (*Client, error) {
42-
return baseNewClient(token, apiHost, oauth, httpTimeoutSeconds, APIVersion)
56+
// we pass maxConcurrent through here so that we can set it differently for tests
57+
func newClient(token string, apiHost string, oauth bool, httpTimeoutSeconds, maxConcurrent int) (*Client, error) {
58+
return baseNewClient(token, apiHost, oauth, httpTimeoutSeconds, APIVersion, maxConcurrent)
4359
}
4460

45-
func newBetaClient(token string, apiHost string, oauth bool, httpTimeoutSeconds int) (*Client, error) {
46-
return baseNewClient(token, apiHost, oauth, httpTimeoutSeconds, "beta")
61+
func newBetaClient(token string, apiHost string, oauth bool, httpTimeoutSeconds, maxConcurrent int) (*Client, error) {
62+
return baseNewClient(token, apiHost, oauth, httpTimeoutSeconds, "beta", maxConcurrent)
4763
}
4864

4965
func newLDClientConfig(apiHost string, httpTimeoutSeconds int, apiVersion string, retryPolicy retryablehttp.CheckRetry) *ldapi.Configuration {
@@ -57,7 +73,7 @@ func newLDClientConfig(apiHost string, httpTimeoutSeconds int, apiVersion string
5773
return cfg
5874
}
5975

60-
func baseNewClient(token string, apiHost string, oauth bool, httpTimeoutSeconds int, apiVersion string) (*Client, error) {
76+
func baseNewClient(token string, apiHost string, oauth bool, httpTimeoutSeconds int, apiVersion string, maxConcurrent int) (*Client, error) {
6177
if token == "" {
6278
return nil, errors.New("token cannot be empty")
6379
}
@@ -84,6 +100,7 @@ func baseNewClient(token string, apiHost string, oauth bool, httpTimeoutSeconds
84100
ld404Retry: ldapi.NewAPIClient(configWith404Retries),
85101
ctx: ctx,
86102
fallbackClient: fallbackClient,
103+
semaphore: semaphore.NewWeighted(int64(maxConcurrent)),
87104
}, nil
88105
}
89106

launchdarkly/config_test.go

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"net/http"
55
"net/http/httptest"
66
"strconv"
7+
"sync"
8+
"sync/atomic"
79
"testing"
810
"time"
911

@@ -24,7 +26,7 @@ func TestHandleRateLimits(t *testing.T) {
2426
defer ts.Close()
2527

2628
// create a client
27-
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S)
29+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
2830
require.NoError(t, err)
2931

3032
res, err := client.ld.GetConfig().HTTPClient.Get(ts.URL)
@@ -46,7 +48,7 @@ func TestHandleRateLimits(t *testing.T) {
4648
defer ts.Close()
4749

4850
// create a client
49-
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S)
51+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
5052
require.NoError(t, err)
5153

5254
res, err := client.ld.GetConfig().HTTPClient.Get(ts.URL)
@@ -74,7 +76,7 @@ func TestHandleRateLimits(t *testing.T) {
7476
defer ts.Close()
7577

7678
// create a client
77-
client, err := newClient("token", ts.URL, false, 20)
79+
client, err := newClient("token", ts.URL, false, 20, DEFAULT_MAX_CONCURRENCY)
7880
require.NoError(t, err)
7981

8082
res, err := client.ld.GetConfig().HTTPClient.Get(ts.URL)
@@ -102,7 +104,7 @@ func TestHandleRateLimits(t *testing.T) {
102104
defer ts.Close()
103105

104106
// create a client
105-
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S)
107+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
106108
require.NoError(t, err)
107109

108110
res, err := client.ld.GetConfig().HTTPClient.Get(ts.URL)
@@ -129,7 +131,7 @@ func TestHandleRateLimits(t *testing.T) {
129131
defer ts.Close()
130132

131133
// create a client
132-
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S)
134+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
133135
require.NoError(t, err)
134136

135137
res, err := client.ld.GetConfig().HTTPClient.Get(ts.URL)
@@ -152,7 +154,7 @@ func Test404RetryClient(t *testing.T) {
152154
defer ts.Close()
153155

154156
// create a client
155-
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S)
157+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
156158
require.NoError(t, err)
157159

158160
res, err := client.ld404Retry.GetConfig().HTTPClient.Get(ts.URL)
@@ -173,7 +175,7 @@ func Test404RetryClient(t *testing.T) {
173175
defer ts.Close()
174176

175177
// create a client
176-
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S)
178+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
177179
require.NoError(t, err)
178180

179181
res, err := client.ld404Retry.GetConfig().HTTPClient.Get(ts.URL)
@@ -200,7 +202,7 @@ func Test404RetryClient(t *testing.T) {
200202
defer ts.Close()
201203

202204
// create a client
203-
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S)
205+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
204206
require.NoError(t, err)
205207

206208
res, err := client.ld404Retry.GetConfig().HTTPClient.Get(ts.URL)
@@ -209,3 +211,68 @@ func Test404RetryClient(t *testing.T) {
209211
assert.Equal(t, 3, calls)
210212
})
211213
}
214+
215+
func TestSemaphoreConcurrencyLimits(t *testing.T) {
216+
t.Parallel()
217+
218+
// Track concurrent requests
219+
var concurrentRequests int32
220+
var maxConcurrentRequests int32
221+
222+
// Create a test server that tracks concurrency
223+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
224+
// Increment concurrent requests
225+
current := atomic.AddInt32(&concurrentRequests, 1)
226+
defer atomic.AddInt32(&concurrentRequests, -1)
227+
228+
// Track max concurrent requests
229+
for {
230+
max := atomic.LoadInt32(&maxConcurrentRequests)
231+
if current <= max || atomic.CompareAndSwapInt32(&maxConcurrentRequests, max, current) {
232+
break
233+
}
234+
}
235+
236+
// Simulate some work
237+
time.Sleep(100 * time.Millisecond)
238+
w.WriteHeader(http.StatusOK)
239+
}))
240+
defer ts.Close()
241+
242+
// Create client with max concurrency of 3
243+
maxConcurrency := 2
244+
client, err := newClient("token", ts.URL, false, DEFAULT_HTTP_TIMEOUT_S, maxConcurrency)
245+
require.NoError(t, err)
246+
247+
// Launch 10 simultaneous requests
248+
numRequests := 10
249+
var wg sync.WaitGroup
250+
errors := make(chan error, numRequests)
251+
252+
for i := 0; i < numRequests; i++ {
253+
wg.Add(1)
254+
go func() {
255+
defer wg.Done()
256+
err := client.withConcurrency(client.ctx, func() error {
257+
_, err := client.ld.GetConfig().HTTPClient.Get(ts.URL)
258+
return err
259+
})
260+
if err != nil {
261+
errors <- err
262+
}
263+
}()
264+
}
265+
266+
wg.Wait()
267+
close(errors)
268+
269+
// Check that no errors occurred
270+
for err := range errors {
271+
require.NoError(t, err)
272+
}
273+
274+
// Verify that max concurrent requests never exceeded the semaphore limit
275+
maxConcurrent := atomic.LoadInt32(&maxConcurrentRequests)
276+
assert.LessOrEqual(t, maxConcurrent, int32(maxConcurrency),
277+
"Max concurrent requests (%d) exceeded semaphore limit (%d)", maxConcurrent, maxConcurrency)
278+
}

launchdarkly/data_source_launchdarkly_audit_log_subscription_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func TestAccDataSourceAuditLogSubscription_exists(t *testing.T) {
8181
}
8282

8383
integrationKey := "datadog"
84-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
84+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
8585
require.NoError(t, err)
8686

8787
subscriptionBody := ldapi.SubscriptionPost{
@@ -124,7 +124,7 @@ func TestAccDataSourceAuditLogSubscription_Slack(t *testing.T) {
124124
}
125125

126126
integrationKey := "slack"
127-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
127+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
128128
require.NoError(t, err)
129129

130130
subscriptionBody := ldapi.SubscriptionPost{

launchdarkly/data_source_launchdarkly_environment_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func TestAccDataSourceEnvironment_noMatchReturnsError(t *testing.T) {
4747
if accTest == "" {
4848
t.SkipNow()
4949
}
50-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
50+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
5151
require.NoError(t, err)
5252
projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
5353
projectBody := ldapi.ProjectPost{
@@ -87,7 +87,7 @@ func TestAccDataSourceEnv_exists(t *testing.T) {
8787
envName := "Terraform Test Env"
8888
envKey := "tf-test-env"
8989
envColor := "fff000"
90-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
90+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
9191
require.NoError(t, err)
9292

9393
envBody := ldapi.EnvironmentPost{

launchdarkly/data_source_launchdarkly_feature_flag_environment_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func TestAccDataSourceFeatureFlagEnvironment_noMatchReturnsError(t *testing.T) {
6767
projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
6868
envKey := "bad-env"
6969
flagKey := "flag-no-env"
70-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
70+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
7171
require.NoError(t, err)
7272

7373
// create some fake config
@@ -88,7 +88,7 @@ func TestAccDataSourceFeatureFlagEnvironment_exists(t *testing.T) {
8888
projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
8989
envKey := "test"
9090
flagKey := "test-env-config"
91-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
91+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
9292
require.NoError(t, err)
9393

9494
rules := []rule{
@@ -215,7 +215,7 @@ func TestAccDataSourceFeatureFlagEnvironment_WithContextFields(t *testing.T) {
215215
projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
216216
envKey := "test"
217217
flagKey := "test-env-config"
218-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
218+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
219219
require.NoError(t, err)
220220

221221
testContextKind := "test-kind"

launchdarkly/data_source_launchdarkly_feature_flag_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func TestAccDataSourceFeatureFlag_noMatchReturnsError(t *testing.T) {
2626
if accTest == "" {
2727
t.SkipNow()
2828
}
29-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
29+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
3030
require.NoError(t, err)
3131
projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
3232
projectBody := ldapi.ProjectPost{
@@ -63,7 +63,7 @@ func TestAccDataSourceFeatureFlag_exists(t *testing.T) {
6363
}
6464

6565
projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
66-
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S)
66+
client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY)
6767
require.NoError(t, err)
6868

6969
flagName := "Flag Data Source Test"

0 commit comments

Comments
 (0)