-
Notifications
You must be signed in to change notification settings - Fork 17
/
persistent_data_store.go
86 lines (77 loc) · 4.45 KB
/
persistent_data_store.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package subsystems
import (
"io"
"github.com/launchdarkly/go-server-sdk/v7/subsystems/ldstoretypes"
)
// PersistentDataStore is an interface for a data store that holds feature flags and related data in a
// serialized form.
//
// This interface should be used for database integrations, or any other data store implementation that
// stores data in some external service. The SDK will provide its own caching layer on top of the
// persistent data store; the data store implementation should not provide caching, but simply do every
// query or update that the SDK tells it to do.
//
// Implementations must be safe for concurrent access from multiple goroutines.
//
// Error handling is defined as follows: if any data store operation encounters a database error, or
// is otherwise unable to complete its task, it should return an error value to make the SDK aware of
// The SDK will log the exception and will assume that the data store is now in a non-operational
// non-operational state; the SDK will then start polling IsStoreAvailable() to determine when the
// store has started working again.
//
// Whenever a new implementation of this interface is written, it should have unit tests that use
// testhelpers.storetest.PersistentDataStoreTestSuite. This ensures that all of the interface methods
// are exercised consistently in various scenarios that might be encountered in real SDK usage.
type PersistentDataStore interface {
io.Closer
// Init overwrites the store's contents with a set of items for each collection.
//
// All previous data should be discarded, regardless of versioning.
//
// The update should be done atomically. If it cannot be done atomically, then the store
// must first add or update each item in the same order that they are given in the input
// data, and then delete any previously stored items that were not in the input data.
Init(allData []ldstoretypes.SerializedCollection) error
// Get retrieves an item from the specified collection, if available.
//
// If the specified key does not exist in the collection, it should return a SerializedItemDescriptor
// with a Version of -1 and an Item of nil.
//
// If the item has been deleted and the store contains a placeholder, it should return that
// placeholder rather than filtering it out.
Get(kind ldstoretypes.DataKind, key string) (ldstoretypes.SerializedItemDescriptor, error)
// GetAll retrieves all items from the specified collection.
//
// If the store contains placeholders for deleted items, it should include them in the results,
// not filter them out.
GetAll(kind ldstoretypes.DataKind) ([]ldstoretypes.KeyedSerializedItemDescriptor, error)
// Upsert updates or inserts an item in the specified collection. For updates, the object will only be
// updated if the existing version is less than the new version.
//
// The SDK may pass a SerializedItemDescriptor that represents a placeholder for a deleted item. In
// that case, assuming the version is greater than any existing version of that item, the store should
// retain that placeholder rather than simply not storing anything.
//
// The method returns the updated item if the update was successful; or, if the update was not
// successful because the store contained an equal or higher version, it returns the item that is
// in the store.
Upsert(kind ldstoretypes.DataKind, key string, item ldstoretypes.SerializedItemDescriptor) (bool, error)
// IsInitialized returns true if the data store contains a data set, meaning that Init has been
// called at least once.
//
// In a shared data store, it should be able to detect this even if Init was called in a
// different process: that is, the test should be based on looking at what is in the data store.
// Once this has been determined to be true, it can continue to return true without having to
// check the store again; this method should be as fast as possible since it may be called during
// feature flag evaluations.
IsInitialized() bool
// IsStoreAvailable tests whether the data store seems to be functioning normally.
//
// This should not be a detailed test of different kinds of operations, but just the smallest possible
// operation to determine whether (for instance) we can reach the database.
//
// Whenever one of the store's other methods returns an error, the SDK will assume that it may have
// become unavailable (e.g. the database connection was lost). The SDK will then call
// IsStoreAvailable() at intervals until it returns true.
IsStoreAvailable() bool
}