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

refactor: add internal data system config #185

Draft
wants to merge 71 commits into
base: v7
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
0988889
refactor: add internal data system config
cwaldren-ld Aug 28, 2024
46814dd
more docs
cwaldren-ld Aug 29, 2024
0efda7a
refactor persistent store config
cwaldren-ld Aug 30, 2024
cfc7c25
make package name shorter in import
cwaldren-ld Sep 6, 2024
17a4179
adding a V2 method to existing data sources
cwaldren-ld Sep 6, 2024
ebae2cf
creating the dataSystem interface
cwaldren-ld Sep 6, 2024
71e1fb7
tests pass
cwaldren-ld Sep 6, 2024
e4b2ea7
lints
cwaldren-ld Sep 6, 2024
e706bd1
add concept of DataStatus, remove need to check initialized
cwaldren-ld Sep 6, 2024
618609a
create stub fdv2 data system
cwaldren-ld Sep 6, 2024
3c6cac4
add dual-mode store
cwaldren-ld Sep 7, 2024
33b0ae8
refactoring the store component
cwaldren-ld Sep 10, 2024
d814a16
comment
cwaldren-ld Sep 10, 2024
8fef482
doc comments
cwaldren-ld Sep 10, 2024
3e93a66
copious comments
cwaldren-ld Sep 10, 2024
a99a329
adding store unit tests
cwaldren-ld Sep 10, 2024
b4e0e4b
use pointer swap to switch stores
cwaldren-ld Sep 10, 2024
98d660b
goimports
cwaldren-ld Sep 10, 2024
6bbf09e
more store unit tests
cwaldren-ld Sep 10, 2024
64b8074
revert changes to StreamingDataSourceBuilder, and make a V2 struct in…
cwaldren-ld Sep 10, 2024
460a1fb
remove now-unnecessary ToSynchronizer converter
cwaldren-ld Sep 10, 2024
dac8e9d
make v2 data sources implement Synchronizer
cwaldren-ld Sep 10, 2024
bfb1e25
ensure closeWhenReady is closed in offline mode
cwaldren-ld Sep 11, 2024
8579fe4
expose some fdv2 types in datasourcev2, and use them to implement e2e…
cwaldren-ld Sep 11, 2024
169df91
break out data destination/status reporter from DataSourceUpdateSink …
cwaldren-ld Sep 11, 2024
b6da0da
make separate test file for fdv2 e2e tests
cwaldren-ld Sep 12, 2024
7d15862
use top-level cfg.Offline to determine if data system should be enabled
cwaldren-ld Sep 12, 2024
155b24a
add dedicated FDv2 streaming protocol builder for unit tests
cwaldren-ld Sep 12, 2024
543b387
add another unit test
cwaldren-ld Sep 13, 2024
d30042d
more fdv2 parity e2e tests
cwaldren-ld Sep 14, 2024
99cffc2
goimports
cwaldren-ld Sep 14, 2024
c47eb1b
merge dataSystem refactor changes
cwaldren-ld Sep 17, 2024
7d46d80
Merge branch 'v7' into cw/sc-254717/data-system-config
cwaldren-ld Sep 17, 2024
5ed8607
Merge branch 'v7' into cw/sc-254717/data-system-config
cwaldren-ld Sep 17, 2024
e260858
Merge branch 'v7' into cw/sc-254717/data-system-config
cwaldren-ld Sep 18, 2024
5f6af74
chore: add fdv2 store
cwaldren-ld Sep 17, 2024
941fee4
remove old comment
cwaldren-ld Sep 18, 2024
d11e039
introduce DataQuality enum
cwaldren-ld Sep 18, 2024
4d03305
add SetPersist
cwaldren-ld Sep 19, 2024
e28b97f
Merge branch 'cw/sdk-557/fdv2-store' into cw/sc-254717/data-system-co…
cwaldren-ld Sep 19, 2024
02f2627
plumbing the persist bool around the store implementation
cwaldren-ld Sep 19, 2024
24f380e
use persist concept
cwaldren-ld Sep 19, 2024
097429e
make store implement FDv2 protocol
cwaldren-ld Sep 20, 2024
c72dd6d
remove old data destination interface
cwaldren-ld Sep 20, 2024
c530451
revert chnages to datasource/streaming_data_source_events.go
cwaldren-ld Sep 21, 2024
01aa57b
use fdv2 types in streaming data source event handler
cwaldren-ld Sep 21, 2024
aa67ce4
refactor concurrency tests
cwaldren-ld Sep 21, 2024
2a54265
optimize comments on store.go
cwaldren-ld Sep 21, 2024
76da39e
add dump method to memory store for atomically getting segments and f…
cwaldren-ld Sep 21, 2024
f4772f6
inMemoryStore tests for SetBasis/ApplyDelta
cwaldren-ld Sep 23, 2024
521c1d3
add new memorystorev2 package
cwaldren-ld Sep 23, 2024
0d2f8e9
update tests
cwaldren-ld Sep 23, 2024
d853f88
more unit tests
cwaldren-ld Sep 23, 2024
3e5a64d
chore: introduce memorystorev2
cwaldren-ld Sep 24, 2024
84b493c
benchmarks
cwaldren-ld Sep 24, 2024
6432563
lints
cwaldren-ld Sep 24, 2024
746c1a8
use defer pattern for locks
cwaldren-ld Sep 24, 2024
b0c8a7c
make element matcher consistent
cwaldren-ld Sep 24, 2024
eaab968
doc tweaks
cwaldren-ld Sep 24, 2024
fd652d1
Merge branch 'cw/sdk-709/memory-store' into cw/sdk-557/fdv2-store
cwaldren-ld Sep 24, 2024
4dbfe23
Merge branch 'cw/sdk-557/fdv2-store' into cw/sc-254717/data-system-co…
cwaldren-ld Sep 24, 2024
4392516
fix broken tests by refactoring fdv2 data model into single package
cwaldren-ld Sep 24, 2024
47f8748
remove some unused interface implementation from fdv2proto.RawEvent
cwaldren-ld Sep 24, 2024
c1ae8a4
refactoring selector
cwaldren-ld Sep 24, 2024
b755ed9
add better collection matcher
cwaldren-ld Sep 24, 2024
b60b1f9
Merge branch 'cw/sdk-557/fdv2-store' into cw/sc-254717/data-system-co…
cwaldren-ld Sep 24, 2024
6469c5c
Merge branch 'v7' into cw/sc-254717/data-system-config
cwaldren-ld Oct 8, 2024
7008d63
remove obsolete file
cwaldren-ld Oct 8, 2024
15168a8
fixing some lints
cwaldren-ld Oct 8, 2024
67a0a7d
more lints
cwaldren-ld Oct 8, 2024
d1700f0
Merge branch 'v7' into cw/sc-254717/data-system-config
cwaldren-ld Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,41 @@ type Config struct {
// LaunchDarkly provides integration packages, and most applications will not
// need to implement their own hooks.
Hooks []ldhooks.Hook

// This field is not stable, and not subject to any backwards compatibility guarantees or semantic versioning.
// It is not suitable for production usage. Do not use it. You have been warned.
//
// DataSystem configures how data (e.g. flags, segments) are retrieved by the SDK.
//
// Set this field only if you want to specify non-default values for any of the data system configuration,
// such as defining an alternate data source or setting up a persistent store.
//
// Below, the default configuration is described with the relevant config item in parentheses:
// 1. The SDK will first attempt to fetch all data from LaunchDarkly's global Content Delivery Network (Initializer)
// 2. It will then establish a streaming connection with LaunchDarkly's realtime Flag Delivery Network (Primary
// Synchronizer.)
// 3. If at any point the connection to the realtime network is interrupted for a short period of time,
// the connection will be automatically re-established.
// 4. If the connection cannot be re-established over a sustained period, the SDK will begin to make periodic
// requests to LaunchDarkly's global CDN (Secondary Synchronizer)
// 5. After a period of time, the SDK will swap back to the realtime Flag Delivery Network if it becomes
// available again.
//
// The default streaming mode configuration is preferred for most use-cases (DataSystem().StreamingPreferred()).
// Sometimes streaming connections are blocked by firewalls or proxies. If this is the case, a polling-only mode
// can be configured:
//
// config := ld.Config{
// DataSystem: ldcomponents.DataSystem().PollingOnly(),
// }
//
// If you'd like to load data from a local source to provide redundancy if there is a problem
// connecting to LaunchDarkly, you can add a custom initializer:
//
// config := ld.Config {
// DataSystem: ldcomponents.DataSystem().PrependInitializers(myCustomInitializer),
// }
//
// The initializer(s) will run before LaunchDarkly's default initializer.
DataSystem subsystems.ComponentConfigurer[subsystems.DataSystemConfiguration]
}
21 changes: 19 additions & 2 deletions internal/datasourcev2/polling_data_source.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package datasourcev2

import (
"context"
"sync"
"time"

Expand Down Expand Up @@ -72,8 +73,24 @@ func newPollingProcessor(
return pp
}

//nolint:revive // no doc comment for standard method
func (pp *PollingProcessor) Start(closeWhenReady chan<- struct{}) {
//nolint:revive // DataInitializer method.
func (pp *PollingProcessor) Name() string {
return "PollingDataSourceV2"
}

//nolint:revive // DataInitializer method.
func (pp *PollingProcessor) Fetch(_ context.Context) (*subsystems.Basis, error) {
//nolint:godox
// TODO(SDK-752): Plumb the context into the request method.
basis, err := pp.requester.Request()
if err != nil {
return nil, err
}
return &subsystems.Basis{Events: basis.Events(), Selector: basis.Selector(), Persist: true}, nil
}

//nolint:revive // DataSynchronizer method.
func (pp *PollingProcessor) Sync(closeWhenReady chan<- struct{}, _ *fdv2proto.Selector) {
pp.loggers.Infof("Starting LaunchDarkly polling with interval: %+v", pp.pollInterval)

ticker := newTickerWithInitialTick(pp.pollInterval)
Expand Down
17 changes: 13 additions & 4 deletions internal/datasourcev2/streaming_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

"github.com/launchdarkly/go-server-sdk/v7/internal/fdv2proto"

"context"

"github.com/launchdarkly/go-jsonstream/v3/jreader"
"github.com/launchdarkly/go-sdk-common/v3/ldlog"
"github.com/launchdarkly/go-sdk-common/v3/ldtime"
Expand Down Expand Up @@ -89,7 +91,6 @@
connectionAttemptLock sync.Mutex
readyOnce sync.Once
closeOnce sync.Once
persist bool
}

// NewStreamProcessor creates the internal implementation of the streaming data source.
Expand All @@ -106,7 +107,6 @@
loggers: context.GetLogging().Loggers,
halt: make(chan struct{}),
cfg: cfg,
persist: true,
}
if cci, ok := context.(*internal.ClientContextImpl); ok {
sp.diagnosticsManager = cci.DiagnosticsManager
Expand All @@ -122,13 +122,22 @@
return sp
}

//nolint:revive // DataInitializer method.
func (sp *StreamProcessor) Name() string {
return "StreamingDataSourceV2"
}

func (sp *StreamProcessor) Fetch(_ context.Context) (*subsystems.Basis, error) {

Check failure on line 130 in internal/datasourcev2/streaming_data_source.go

View workflow job for this annotation

GitHub Actions / ldotel Linux, Go 1.22

exported: exported method StreamProcessor.Fetch should have comment or be unexported (revive)

Check failure on line 130 in internal/datasourcev2/streaming_data_source.go

View workflow job for this annotation

GitHub Actions / ldotel Linux, Go 1.18

exported: exported method StreamProcessor.Fetch should have comment or be unexported (revive)

Check failure on line 130 in internal/datasourcev2/streaming_data_source.go

View workflow job for this annotation

GitHub Actions / Linux, Go 1.23 / Unit Tests and Coverage

exported: exported method StreamProcessor.Fetch should have comment or be unexported (revive)

Check failure on line 130 in internal/datasourcev2/streaming_data_source.go

View workflow job for this annotation

GitHub Actions / Linux, Go 1.22 / Unit Tests and Coverage

exported: exported method StreamProcessor.Fetch should have comment or be unexported (revive)

Check failure on line 130 in internal/datasourcev2/streaming_data_source.go

View workflow job for this annotation

GitHub Actions / ldotel Linux, Go 1.23

exported: exported method StreamProcessor.Fetch should have comment or be unexported (revive)

Check failure on line 130 in internal/datasourcev2/streaming_data_source.go

View workflow job for this annotation

GitHub Actions / Linux, Go 1.18 / Unit Tests and Coverage

exported: exported method StreamProcessor.Fetch should have comment or be unexported (revive)
return nil, errors.New("StreamProcessor does not implement Fetch capability")
}

//nolint:revive // no doc comment for standard method
func (sp *StreamProcessor) IsInitialized() bool {
return sp.isInitialized.Get()
}

//nolint:revive // no doc comment for standard method
func (sp *StreamProcessor) Start(closeWhenReady chan<- struct{}) {
//nolint:revive // DataSynchronizer method.
func (sp *StreamProcessor) Sync(closeWhenReady chan<- struct{}, _ *fdv2proto.Selector) {
sp.loggers.Info("Starting LaunchDarkly streaming connection")
go sp.subscribe(closeWhenReady)
}
Expand Down
20 changes: 17 additions & 3 deletions internal/datastore/data_store_status_provider_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,33 @@

import (
"github.com/launchdarkly/go-server-sdk/v7/interfaces"
"github.com/launchdarkly/go-server-sdk/v7/subsystems"
)

type StatusMonitorable interface {

Check failure on line 7 in internal/datastore/data_store_status_provider_impl.go

View workflow job for this annotation

GitHub Actions / ldotel Linux, Go 1.22

exported: exported type StatusMonitorable should have comment or be unexported (revive)

Check failure on line 7 in internal/datastore/data_store_status_provider_impl.go

View workflow job for this annotation

GitHub Actions / ldotel Linux, Go 1.18

exported: exported type StatusMonitorable should have comment or be unexported (revive)

Check failure on line 7 in internal/datastore/data_store_status_provider_impl.go

View workflow job for this annotation

GitHub Actions / Linux, Go 1.23 / Unit Tests and Coverage

exported: exported type StatusMonitorable should have comment or be unexported (revive)

Check failure on line 7 in internal/datastore/data_store_status_provider_impl.go

View workflow job for this annotation

GitHub Actions / Linux, Go 1.22 / Unit Tests and Coverage

exported: exported type StatusMonitorable should have comment or be unexported (revive)

Check failure on line 7 in internal/datastore/data_store_status_provider_impl.go

View workflow job for this annotation

GitHub Actions / ldotel Linux, Go 1.23

exported: exported type StatusMonitorable should have comment or be unexported (revive)

Check failure on line 7 in internal/datastore/data_store_status_provider_impl.go

View workflow job for this annotation

GitHub Actions / Linux, Go 1.18 / Unit Tests and Coverage

exported: exported type StatusMonitorable should have comment or be unexported (revive)
// IsStatusMonitoringEnabled returns true if this data store implementation supports status
// monitoring.
//
// This is normally only true for persistent data stores created with ldcomponents.PersistentDataStore(),
// but it could also be true for any custom DataStore implementation that makes use of the
// statusUpdater parameter provided to the DataStoreFactory. Returning true means that the store
// guarantees that if it ever enters an invalid state (that is, an operation has failed or it knows
// that operations cannot succeed at the moment), it will publish a status update, and will then
// publish another status update once it has returned to a valid state.
//
// The same value will be returned from DataStoreStatusProvider.IsStatusMonitoringEnabled().
IsStatusMonitoringEnabled() bool
}

// dataStoreStatusProviderImpl is the internal implementation of DataStoreStatusProvider. It's not
// exported because the rest of the SDK code only interacts with the public interface.
type dataStoreStatusProviderImpl struct {
store subsystems.DataStore
store StatusMonitorable
dataStoreUpdates *DataStoreUpdateSinkImpl
}

// NewDataStoreStatusProviderImpl creates the internal implementation of DataStoreStatusProvider.
func NewDataStoreStatusProviderImpl(
store subsystems.DataStore,
store StatusMonitorable,
dataStoreUpdates *DataStoreUpdateSinkImpl,
) interfaces.DataStoreStatusProvider {
return &dataStoreStatusProviderImpl{
Expand Down
Loading
Loading