From 7d6d7d8ecb2213256b5f9aa85a51947d7c2b4f0d Mon Sep 17 00:00:00 2001 From: Todd Anderson Date: Thu, 26 Feb 2026 13:57:52 -0500 Subject: [PATCH 1/4] chore: commonizes several FDv2 related types --- .../com/launchdarkly/sdk/fdv2/ChangeSet.java | 104 ++++++++++++++++++ .../launchdarkly/sdk/fdv2/ChangeSetType.java | 21 ++++ .../com/launchdarkly/sdk/fdv2/Selector.java | 78 +++++++++++++ .../sdk/fdv2/SourceResultType.java | 18 +++ .../launchdarkly/sdk/fdv2/SourceSignal.java | 29 +++++ .../launchdarkly/sdk/fdv2/package-info.java | 7 ++ 6 files changed, 257 insertions(+) create mode 100644 lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSet.java create mode 100644 lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSetType.java create mode 100644 lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/Selector.java create mode 100644 lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceResultType.java create mode 100644 lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceSignal.java create mode 100644 lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/package-info.java diff --git a/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSet.java b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSet.java new file mode 100644 index 00000000..20c77bf0 --- /dev/null +++ b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSet.java @@ -0,0 +1,104 @@ +package com.launchdarkly.sdk.fdv2; + +import java.util.Objects; + +/** + * Represents a set of changes to apply to a data store. + * + * @param the type of the data payload + */ +public final class ChangeSet { + private final ChangeSetType type; + private final Selector selector; + private final String environmentId; + private final T data; + private final boolean shouldPersist; + + /** + * Constructs a new ChangeSet. + *

+ * When implementing a custom data source, pass {@link Selector#EMPTY} for the {@code selector} + * parameter. Non-empty selectors are only meaningful for LaunchDarkly's own data sources. + * + * @param type the type of the changeset + * @param selector the selector for this change; null is normalized to {@link Selector#EMPTY} + * @param data the data payload + * @param environmentId the environment ID, or null if not available + * @param shouldPersist true if the data should be persisted to persistent stores + */ + public ChangeSet(ChangeSetType type, Selector selector, T data, String environmentId, boolean shouldPersist) { + this.type = type; + this.selector = selector != null ? selector : Selector.EMPTY; + this.data = data; + this.environmentId = environmentId; + this.shouldPersist = shouldPersist; + } + + /** + * Returns the type of the changeset. + * + * @return the changeset type + */ + public ChangeSetType getType() { + return type; + } + + /** + * Returns the selector for this change. Will not be null; may be {@link Selector#EMPTY}. + * + * @return the selector + */ + public Selector getSelector() { + return selector; + } + + /** + * Returns the environment ID associated with the change, or null if not available. + * + * @return the environment ID, or null + */ + public String getEnvironmentId() { + return environmentId; + } + + /** + * Returns the data payload for this changeset. + * + * @return the data + */ + public T getData() { + return data; + } + + /** + * Returns whether this data should be persisted to persistent stores. + * + * @return true if the data should be persisted, false otherwise + */ + public boolean shouldPersist() { + return shouldPersist; + } + + @Override + public boolean equals(Object o) { + if (o instanceof ChangeSet) { + ChangeSet other = (ChangeSet) o; + return type == other.type + && shouldPersist == other.shouldPersist + && Objects.equals(selector, other.selector) + && Objects.equals(environmentId, other.environmentId) + && Objects.equals(data, other.data); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(type, selector, environmentId, data, shouldPersist); + } + + @Override + public String toString() { + return "ChangeSet(" + type + "," + selector + "," + environmentId + "," + data + "," + shouldPersist + ")"; + } +} diff --git a/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSetType.java b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSetType.java new file mode 100644 index 00000000..68ecc7f4 --- /dev/null +++ b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/ChangeSetType.java @@ -0,0 +1,21 @@ +package com.launchdarkly.sdk.fdv2; + +/** + * Indicates the type of a change set applied to a data store. + */ +public enum ChangeSetType { + /** + * Represents a full store update which replaces all data currently in the store. + */ + Full, + + /** + * Represents an incremental set of changes to be applied to the existing data in the store. + */ + Partial, + + /** + * Indicates that there are no changes; the changeset may still carry a selector to store. + */ + None +} diff --git a/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/Selector.java b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/Selector.java new file mode 100644 index 00000000..b48e80c7 --- /dev/null +++ b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/Selector.java @@ -0,0 +1,78 @@ +package com.launchdarkly.sdk.fdv2; + +/** + * Identifies a specific version of data in the LaunchDarkly backend, used to request incremental + * updates from a known point. + *

+ * A selector is either empty ({@link #EMPTY}) or contains a version number and state string that + * were provided by a LaunchDarkly data source. Empty selectors signal that the client has no + * existing data and requires a full payload. + *

+ * For SDK consumers implementing custom data sources: you should always use + * {@link #EMPTY} when constructing a {@link ChangeSet}. Non-empty selectors are set by + * LaunchDarkly's own data sources based on state received from the LaunchDarkly backend, and + * are not meaningful when constructed externally. + */ +public final class Selector { + private final boolean isEmpty; + private final int version; + private final String state; + + private Selector(int version, String state, boolean isEmpty) { + this.version = version; + this.state = state; + this.isEmpty = isEmpty; + } + + /** + * If true, then this selector is empty. An empty selector cannot be used as a basis for + * requesting incremental updates from a data source. + * + * @return whether the selector is empty + */ + public boolean isEmpty() { + return isEmpty; + } + + /** + * The version of the data associated with this selector. + * + * @return the version + */ + public int getVersion() { + return version; + } + + /** + * The state associated with the payload. + * + * @return the state identifier, or null if empty + */ + public String getState() { + return state; + } + + static Selector empty() { + return new Selector(0, null, true); + } + + /** + * Creates a new Selector with the given version and state. + *

+ * This method is intended for use by LaunchDarkly data sources only. + * Custom data source implementations should use {@link #EMPTY} instead. + * + * @param version the version number + * @param state the state identifier + * @return a new Selector instance + */ + public static Selector make(int version, String state) { + return new Selector(version, state, false); + } + + /** + * An empty selector instance. Custom data source implementations should always use this + * value when constructing a {@link ChangeSet}. + */ + public static final Selector EMPTY = empty(); +} diff --git a/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceResultType.java b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceResultType.java new file mode 100644 index 00000000..7ea7ce58 --- /dev/null +++ b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceResultType.java @@ -0,0 +1,18 @@ +package com.launchdarkly.sdk.fdv2; + +/** + * Indicates whether an FDv2 source result carries a change set or a status update. + */ +public enum SourceResultType { + /** + * The source has emitted a change set. This implies that the source is in a valid state. + */ + CHANGE_SET, + + /** + * The source is emitting a status update, indicating a transition from being valid to being + * in some kind of error or non-operational state. The source will emit a {@link #CHANGE_SET} + * if it becomes valid again. + */ + STATUS, +} diff --git a/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceSignal.java b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceSignal.java new file mode 100644 index 00000000..24fe0bb1 --- /dev/null +++ b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/SourceSignal.java @@ -0,0 +1,29 @@ +package com.launchdarkly.sdk.fdv2; + +/** + * Represents the state of an FDv2 data source when emitting a status result. + */ +public enum SourceSignal { + /** + * The data source has encountered an interruption and will attempt to reconnect. This is not + * intended to be used with an initializer; use {@link #TERMINAL_ERROR} instead. When used with + * an initializer it will still be treated as a terminal state. + */ + INTERRUPTED, + + /** + * The data source has been shut down and will not produce any further results. + */ + SHUTDOWN, + + /** + * The data source has encountered a terminal error and will not produce any further results. + */ + TERMINAL_ERROR, + + /** + * The data source has been instructed to disconnect (e.g. the server sent a goodbye message) + * and will not produce any further results. + */ + GOODBYE, +} diff --git a/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/package-info.java b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/package-info.java new file mode 100644 index 00000000..09719056 --- /dev/null +++ b/lib/shared/common/src/main/java/com/launchdarkly/sdk/fdv2/package-info.java @@ -0,0 +1,7 @@ +/** + * Types for the FDv2 (Flag Delivery v2) data source protocol. + *

+ * This package contains the public types used by SDK data source implementations that support + * the FDv2 data sources. + */ +package com.launchdarkly.sdk.fdv2; From 143146097bc77c71ca399f9dd84363a7c7ff6e4d Mon Sep 17 00:00:00 2001 From: Todd Anderson Date: Thu, 26 Feb 2026 14:00:07 -0500 Subject: [PATCH 2/4] chore: commonizes several FDv2 related types --- .../buildSrc/src/main/kotlin/Dependencies.kt | 2 +- .../internal/fdv2/sources/FDv2ChangeSet.java | 1 + .../fdv2/sources/FDv2ProtocolHandler.java | 1 + .../sdk/internal/fdv2/sources/Selector.java | 65 ------------------- 4 files changed, 3 insertions(+), 66 deletions(-) delete mode 100644 lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/Selector.java diff --git a/lib/shared/internal/buildSrc/src/main/kotlin/Dependencies.kt b/lib/shared/internal/buildSrc/src/main/kotlin/Dependencies.kt index 747c2df3..89a5f147 100644 --- a/lib/shared/internal/buildSrc/src/main/kotlin/Dependencies.kt +++ b/lib/shared/internal/buildSrc/src/main/kotlin/Dependencies.kt @@ -4,7 +4,7 @@ object Versions { const val gson = "2.13.1" - const val launchdarklyJavaSdkCommon = "2.1.2" + const val launchdarklyJavaSdkCommon = "2.4.0" const val launchdarklyLogging = "1.1.1" const val okhttp = "4.12.0" const val testHelpers = "1.2.0" diff --git a/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ChangeSet.java b/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ChangeSet.java index 8ffc69e1..41d8eb4b 100644 --- a/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ChangeSet.java +++ b/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ChangeSet.java @@ -1,6 +1,7 @@ package com.launchdarkly.sdk.internal.fdv2.sources; import com.google.gson.JsonElement; +import com.launchdarkly.sdk.fdv2.Selector; import java.util.Collections; import java.util.List; diff --git a/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ProtocolHandler.java b/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ProtocolHandler.java index 5bdd7fc8..a00b48a8 100644 --- a/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ProtocolHandler.java +++ b/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/FDv2ProtocolHandler.java @@ -1,5 +1,6 @@ package com.launchdarkly.sdk.internal.fdv2.sources; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.internal.fdv2.payloads.DeleteObject; import com.launchdarkly.sdk.internal.fdv2.payloads.Error; import com.launchdarkly.sdk.internal.fdv2.payloads.FDv2Event; diff --git a/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/Selector.java b/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/Selector.java deleted file mode 100644 index 5d13844c..00000000 --- a/lib/shared/internal/src/main/java/com/launchdarkly/sdk/internal/fdv2/sources/Selector.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.launchdarkly.sdk.internal.fdv2.sources; - -/** - * A selector can either be empty or it can contain state and a version. - */ -public final class Selector { - private final boolean isEmpty; - private final int version; - private final String state; - - private Selector(int version, String state, boolean isEmpty) { - this.version = version; - this.state = state; - this.isEmpty = isEmpty; - } - - /** - * If true, then this selector is empty. An empty selector cannot be used as a basis for a data source. - * - * @return whether the selector is empty - */ - public boolean isEmpty() { - return isEmpty; - } - - /** - * The version of the data associated with this selector. - * - * @return the version - */ - public int getVersion() { - return version; - } - - /** - * The state associated with the payload. - * - * @return the state identifier, or null if empty - */ - public String getState() { - return state; - } - - static Selector empty() { - return new Selector(0, null, true); - } - - /** - * Creates a new Selector with the given version and state. - * - * @param version the version number - * @param state the state identifier - * @return a new Selector instance - */ - public static Selector make(int version, String state) { - return new Selector(version, state, false); - } - - /** - * An empty selector instance. - */ - public static final Selector EMPTY = empty(); -} - - From 4b214e1deeb2d3624d44052e2b7d163ea821640f Mon Sep 17 00:00:00 2001 From: Todd Anderson Date: Thu, 26 Feb 2026 15:01:53 -0500 Subject: [PATCH 3/4] chore: commonizes several FDv2 related types --- lib/sdk/server/build.gradle | 2 +- .../main/java/com/launchdarkly/sdk/.DS_Store | Bin 0 -> 8196 bytes .../sdk/server/DataModelDependencies.java | 6 +- .../server/DataSourceSynchronizerAdapter.java | 31 ++-- .../sdk/server/DataSourceUpdatesImpl.java | 24 ++-- .../sdk/server/DefaultFDv2Requestor.java | 2 +- .../sdk/server/FDv2ChangeSetTranslator.java | 11 +- .../sdk/server/FDv2DataSourceConditions.java | 6 +- .../sdk/server/FDv2Requestor.java | 2 +- .../sdk/server/InMemoryDataStore.java | 8 +- .../launchdarkly/sdk/server/PollingBase.java | 12 +- .../sdk/server/SelectorSourceFacade.java | 2 +- .../sdk/server/StreamingSynchronizerImpl.java | 9 +- .../sdk/server/WriteThroughStore.java | 15 +- .../server/datasources/FDv2SourceResult.java | 86 ++++------- .../server/datasources/SelectorSource.java | 2 +- .../integrations/FileDataSourceBase.java | 10 +- .../integrations/FileDataSourceImpl.java | 12 +- .../server/integrations/FileInitializer.java | 6 +- .../sdk/server/integrations/TestDataV2.java | 11 +- .../sdk/server/subsystems/DataStoreTypes.java | 131 +---------------- .../TransactionalDataSourceUpdateSink.java | 9 +- .../subsystems/TransactionalDataStore.java | 10 +- .../sdk/server/DataModelDependenciesTest.java | 30 ++-- .../DataSourceSynchronizerAdapterTest.java | 22 +-- .../sdk/server/DataSourceUpdatesImplTest.java | 18 +-- .../sdk/server/DefaultFDv2RequestorTest.java | 2 +- .../server/FDv2ChangeSetTranslatorTest.java | 92 ++++++------ .../FDv2DataSourceFallbackConditionTest.java | 27 ++-- .../FDv2DataSourceRecoveryConditionTest.java | 18 ++- .../sdk/server/FDv2DataSourceTest.java | 21 ++- .../sdk/server/InMemoryDataStoreTest.java | 40 +++--- .../server/PollingInitializerImplTest.java | 66 ++++----- .../server/PollingSynchronizerImplTest.java | 80 ++++++----- .../server/StreamingSynchronizerImplTest.java | 136 +++++++++--------- .../sdk/server/TestComponents.java | 7 +- .../sdk/server/WriteThroughStoreTest.java | 42 +++--- .../integrations/FileInitializerTest.java | 28 ++-- .../integrations/FileSynchronizerTest.java | 34 ++--- .../TestDataSourceBuildInputs.java | 2 +- .../sdk/server/integrations/TestDataTest.java | 7 +- .../server/integrations/TestDataV2Test.java | 33 ++--- 42 files changed, 511 insertions(+), 601 deletions(-) create mode 100644 lib/sdk/server/src/main/java/com/launchdarkly/sdk/.DS_Store diff --git a/lib/sdk/server/build.gradle b/lib/sdk/server/build.gradle index b5c9ea79..c683f281 100644 --- a/lib/sdk/server/build.gradle +++ b/lib/sdk/server/build.gradle @@ -71,7 +71,7 @@ ext.versions = [ "guava": "32.0.1-jre", "jackson": "2.11.2", "launchdarklyJavaSdkCommon": "2.3.0", - "launchdarklyJavaSdkInternal": "1.7.0", + "launchdarklyJavaSdkInternal": "1.9.0", "launchdarklyLogging": "1.1.0", "okhttp": "4.12.0", // specify this for the SDK build instead of relying on the transitive dependency from okhttp-eventsource "okhttpEventsource": "4.2.0", diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/.DS_Store b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..34b87da408a26f58094d9a773ae21ceb17c8ab2e GIT binary patch literal 8196 zcmeHMOK=oL818TKV3v%@1fto*onj%OkW>iaVI?3~o0k&I1K7lDVkGSDjAU>!v+V3{ z!ozaQDlZCHp0s>>(vp&c1!{TmpdxzIc)+qeP-^)&;K7T^!M~>`l-ZD*WuZ)0b${Fc z-+%Y?-`_u-f5I3;cV6GZSeP*;Q{|{uQFDXB^}H@Ak}oME1lcoYu&m`4dQz5?S~5Bi z1Re-H5O^T)K;VJE12=;Q=+5RvUgq8x+Mo?Q5P0C0^ZiM173;SQO})(wriDfNu&v#egs;eUuL;jQLm;D9jmzIfK74{0s%&>SP!7 zhBL$j25sPhzynJ?z;pLX=JL#)6&C03W${$TGTmHz``3`l$}1{Y$f1>0%5BiVa>z1ez6RwlZ^>~v_scPOe4j43-SulEOMmJ&7lH9Pa zWRD1)tFB+ueAlL}9lK(E{e%1GYt-6RtLqeH!qg2rXFg&Y+0j{3&rOdf-LzrrrhRy< zV7g|?GDhs=j8Ti$P-wm;+|YPuMAMcVn#iZjqj@uTOl^{7Z;j|$O_|i`;RYR@ucE6L zWSWOoU%yt<9^#swtU;~r8*FURlo6NqpeFr+ZJQNk&aK^CdkuLdb-$%L$cRHCh zhG%Uf>r3~N)H_m=bE7`p%sHNtyfH+(80XV<>AJUv#&AQ87S~2)^$VGf$g~S)j!uZq zg&^I4sZ6p{7{7FOZqWwz6I}zzz{HPq5SMd3KhaXP>Z(>?`&y z`-xp;zXPa52rE&AIy9mgt+*Q<=)?|mV;K8!0C7xW8YYgw#T<^~1Ww{fJcUy@jWc)- zFXL6bhS%{H-obfXz`OVmm+%=r$CtQ*@9;f-z*YQ#KXFZ}km{wd)F7>sTBS`=o75q7 zN;{={q#VG#XTt4r zwFt1=@2HQiZ`r)Pb9dKuA`0d%koE5&;PHM@w0OMtcu~UHc@c@qnuRDW4ardo7-LT6 zajUKnqt_|TG6jrUA-WrsjWUIbS}D4%kv5rvQkL*`=jhJ4I)d*t)+KJ!yVh@Ih;hf*2 zIEX1Ek%EpH*vQ~0as4D7!{aF82|P_)KZ9rREMCBicnPoI4ZKNwKa01C?eF1ze1MPe zF)rd$pZDJo>wm^CB}^V%%w+sl%H%>kYg>+enB)uWUu+WeZZZ$>yPry!=l^}nfB*Le z1x?_AzytqJ51_m^-rG%kTkgHhbL}YALsWU; sortAllCollections(FullDataSet sortChangeset(ChangeSet inSet) { + public static ChangeSet>>> sortChangeset(ChangeSet>>> inSet) { ImmutableSortedMap.Builder> builder = ImmutableSortedMap.orderedBy(dataKindPriorityOrder); for (Map.Entry> entry: inSet.getData()) { diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapter.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapter.java index c43732e7..b8a354a6 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapter.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapter.java @@ -1,14 +1,19 @@ package com.launchdarkly.sdk.server; import com.launchdarkly.sdk.internal.collections.IterableAsyncQueue; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.Synchronizer; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider; import com.launchdarkly.sdk.server.subsystems.DataSource; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSink; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import java.io.IOException; import java.time.Instant; @@ -127,11 +132,11 @@ public ConvertingUpdateSink(IterableAsyncQueue resultQueue) { } @Override - public boolean init(DataStoreTypes.FullDataSet allData) { + public boolean init(DataStoreTypes.FullDataSet allData) { // Convert the full data set into a ChangeSet and emit it - DataStoreTypes.ChangeSet changeSet = - new DataStoreTypes.ChangeSet<>( - DataStoreTypes.ChangeSetType.Full, + ChangeSet>>> changeSet = + new ChangeSet<>( + ChangeSetType.Full, Selector.EMPTY, allData.getData(), null, @@ -142,18 +147,18 @@ public boolean init(DataStoreTypes.FullDataSet al } @Override - public boolean upsert(DataStoreTypes.DataKind kind, String key, DataStoreTypes.ItemDescriptor item) { + public boolean upsert(DataKind kind, String key, ItemDescriptor item) { // Convert the upsert into a ChangeSet with a single item and emit it - DataStoreTypes.KeyedItems items = - new DataStoreTypes.KeyedItems<>(Collections.>singletonList( + KeyedItems items = + new KeyedItems<>(Collections.>singletonList( new AbstractMap.SimpleEntry<>(key, item))); - Iterable>> data = - Collections.>>singletonList( + Iterable>> data = + Collections.>>singletonList( new AbstractMap.SimpleEntry<>(kind, items)); - DataStoreTypes.ChangeSet changeSet = - new DataStoreTypes.ChangeSet<>( - DataStoreTypes.ChangeSetType.Partial, + ChangeSet>>> changeSet = + new ChangeSet<>( + ChangeSetType.Partial, Selector.EMPTY, data, null, diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceUpdatesImpl.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceUpdatesImpl.java index 051d987e..5b8e5095 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceUpdatesImpl.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataSourceUpdatesImpl.java @@ -14,7 +14,7 @@ import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSink; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSinkV2; import com.launchdarkly.sdk.server.subsystems.DataStore; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; @@ -370,7 +370,7 @@ private static String describeErrorCount(Map.Entry entry) { } @Override - public boolean apply(ChangeSet changeSet) { + public boolean apply(ChangeSet>>> changeSet) { if (store instanceof TransactionalDataStore) { return applyToTransactionalStore((TransactionalDataStore) store, changeSet); } @@ -380,7 +380,7 @@ public boolean apply(ChangeSet changeSet) { } private boolean applyToTransactionalStore(TransactionalDataStore transactionalDataStore, - ChangeSet changeSet) { + ChangeSet>>> changeSet) { Map> oldData; // Getting the old values requires accessing the store, which can fail. // If there is a failure to read the store, then we stop treating it as a failure. @@ -391,7 +391,7 @@ private boolean applyToTransactionalStore(TransactionalDataStore transactionalDa return false; } - ChangeSet sortedChangeSet = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> sortedChangeSet = DataModelDependencies.sortChangeset(changeSet); try { transactionalDataStore.apply(sortedChangeSet); @@ -415,7 +415,7 @@ private boolean applyToTransactionalStore(TransactionalDataStore transactionalDa return true; } - private boolean applyToLegacyStore(ChangeSet sortedChangeSet) { + private boolean applyToLegacyStore(ChangeSet>>> sortedChangeSet) { switch (sortedChangeSet.getType()) { case Full: return applyFullChangeSetToLegacyStore(sortedChangeSet); @@ -427,16 +427,16 @@ private boolean applyToLegacyStore(ChangeSet sortedChangeSet) { } } - private boolean applyFullChangeSetToLegacyStore(ChangeSet unsortedChangeset) { + private boolean applyFullChangeSetToLegacyStore(ChangeSet>>> unsortedChangeset) { // Convert ChangeSet to FullDataSet for legacy init path, preserving shouldPersist flag return init(new FullDataSet<>(unsortedChangeset.getData(), unsortedChangeset.shouldPersist())); } - private boolean applyPartialChangeSetToLegacyStore(ChangeSet changeSet) { + private boolean applyPartialChangeSetToLegacyStore(ChangeSet>>> changeSet) { // Sorting isn't strictly required here, as upsert behavior didn't traditionally have it, // but it also doesn't hurt, and there could be cases where it results in slightly // greater store consistency for persistent stores. - ChangeSet sortedChangeset = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> sortedChangeset = DataModelDependencies.sortChangeset(changeSet); for (Map.Entry> kindItemsPair: sortedChangeset.getData()) { for (Map.Entry item: kindItemsPair.getValue().getItems()) { @@ -471,7 +471,7 @@ private Map> getOldDataIfFlagChangeListene } } - private Map> changeSetToMap(ChangeSet changeSet) { + private Map> changeSetToMap(ChangeSet>>> changeSet) { Map> ret = new HashMap<>(); for (Map.Entry> e: changeSet.getData()) { ret.put(e.getKey(), ImmutableMap.copyOf(e.getValue().getItems())); @@ -481,7 +481,7 @@ private Map> changeSetToMap(ChangeSet updateDependencyTrackerForChangesetAndDetermineChanges( Map> oldDataMap, - ChangeSet changeSet) { + ChangeSet>>> changeSet) { switch (changeSet.getType()) { case Full: return handleFullChangeset(oldDataMap, changeSet); @@ -496,7 +496,7 @@ private Set updateDependencyTrackerForChangesetAndDetermineChanges( private Set handleFullChangeset( Map> oldDataMap, - ChangeSet changeSet) { + ChangeSet>>> changeSet) { dependencyTracker.reset(); for (Map.Entry> kindEntry: changeSet.getData()) { DataKind kind = kindEntry.getKey(); @@ -516,7 +516,7 @@ private Set handleFullChangeset( private Set handlePartialChangeset( Map> oldDataMap, - ChangeSet changeSet) { + ChangeSet>>> changeSet) { if (oldDataMap == null) { // Update dependencies but don't track changes when no listeners for (Map.Entry> kindEntry: changeSet.getData()) { diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DefaultFDv2Requestor.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DefaultFDv2Requestor.java index d41be277..7a7dbeec 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DefaultFDv2Requestor.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DefaultFDv2Requestor.java @@ -2,7 +2,7 @@ import com.launchdarkly.logging.LDLogger; import com.launchdarkly.sdk.internal.fdv2.payloads.FDv2Event; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.internal.http.HttpHelpers; import com.launchdarkly.sdk.internal.http.HttpProperties; diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslator.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslator.java index ba884775..45525f06 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslator.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslator.java @@ -5,8 +5,9 @@ import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ChangeSet; import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ChangeSet.FDv2Change; import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ChangeSet.FDv2ChangeType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; @@ -25,16 +26,16 @@ private FDv2ChangeSetTranslator() { } /** - * Converts an FDv2ChangeSet to a DataStoreTypes.ChangeSet. + * Converts an FDv2ChangeSet to a ChangeSet. * * @param changeset the FDv2 changeset to convert * @param logger logger for diagnostic messages * @param environmentId the environment ID to include in the changeset (may be null) * @param shouldPersist true if the data should be persisted to persistent stores, false otherwise - * @return a DataStoreTypes.ChangeSet containing the converted data + * @return a ChangeSet containing the converted data * @throws IllegalArgumentException if the changeset type is unknown */ - public static DataStoreTypes.ChangeSet toChangeSet( + public static ChangeSet>>> toChangeSet( FDv2ChangeSet changeset, LDLogger logger, String environmentId, @@ -101,7 +102,7 @@ public static DataStoreTypes.ChangeSet toChangeSet( )); } - return new DataStoreTypes.ChangeSet<>( + return new ChangeSet<>( changeSetType, changeset.getSelector(), dataBuilder.build(), diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2DataSourceConditions.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2DataSourceConditions.java index 1eb3abff..30f81b28 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2DataSourceConditions.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2DataSourceConditions.java @@ -1,5 +1,7 @@ package com.launchdarkly.sdk.server; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import java.io.Closeable; @@ -120,13 +122,13 @@ public FallbackCondition(ScheduledExecutorService sharedExecutor, long timeoutSe @Override public void inform(FDv2SourceResult sourceResult) { - if (sourceResult.getResultType() == FDv2SourceResult.ResultType.CHANGE_SET) { + if (sourceResult.getResultType() == SourceResultType.CHANGE_SET) { if (timerFuture != null) { timerFuture.cancel(false); timerFuture = null; } } - if (sourceResult.getResultType() == FDv2SourceResult.ResultType.STATUS && sourceResult.getStatus().getState() == FDv2SourceResult.State.INTERRUPTED) { + if (sourceResult.getResultType() == SourceResultType.STATUS && sourceResult.getStatus().getState() == SourceSignal.INTERRUPTED) { if (timerFuture == null) { timerFuture = sharedExecutor.schedule(() -> { resultFuture.complete(this); diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2Requestor.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2Requestor.java index dbebd9d8..98048a0e 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2Requestor.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2Requestor.java @@ -1,7 +1,7 @@ package com.launchdarkly.sdk.server; import com.launchdarkly.sdk.internal.fdv2.payloads.FDv2Event; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import okhttp3.Headers; import java.util.List; diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/InMemoryDataStore.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/InMemoryDataStore.java index 4e7448f8..2e394990 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/InMemoryDataStore.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/InMemoryDataStore.java @@ -2,11 +2,11 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider.CacheStats; import com.launchdarkly.sdk.server.subsystems.DataStore; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; @@ -122,7 +122,7 @@ public void close() throws IOException { } @Override - public void apply(ChangeSet changeSet) { + public void apply(ChangeSet>>> changeSet) { switch (changeSet.getType()) { case Full: applyFullPayload(changeSet.getData(), changeSet.getEnvironmentId(), changeSet.getSelector(), changeSet.shouldPersist()); diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java index 13e03659..0a570971 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java @@ -3,13 +3,19 @@ import com.launchdarkly.logging.LDLogger; import com.launchdarkly.sdk.internal.fdv2.payloads.FDv2Event; import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ProtocolHandler; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import com.launchdarkly.sdk.json.SerializationException; import java.io.IOException; +import java.util.Map; import java.util.Date; import java.util.concurrent.CompletableFuture; @@ -83,7 +89,7 @@ protected CompletableFuture poll(Selector selector, boolean on // If we get a 304, then that means nothing has changed. if (pollingResponse.getStatusCode() == 304) { return FDv2SourceResult.changeSet( - new DataStoreTypes.ChangeSet<>(DataStoreTypes.ChangeSetType.None, + new ChangeSet<>(ChangeSetType.None, Selector.EMPTY, null, null, // Header derived values will have been handled on initial response. @@ -111,7 +117,7 @@ protected CompletableFuture poll(Selector selector, boolean on case CHANGESET: try { - DataStoreTypes.ChangeSet converted = FDv2ChangeSetTranslator.toChangeSet( + ChangeSet>>> converted = FDv2ChangeSetTranslator.toChangeSet( ((FDv2ProtocolHandler.FDv2ActionChangeset) res).getChangeset(), logger, environmentId, diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/SelectorSourceFacade.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/SelectorSourceFacade.java index 6ce01af7..c09e32da 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/SelectorSourceFacade.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/SelectorSourceFacade.java @@ -1,6 +1,6 @@ package com.launchdarkly.sdk.server; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.datasources.SelectorSource; import com.launchdarkly.sdk.server.subsystems.TransactionalDataStore; diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java index 421ad0d0..dc24e761 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java @@ -16,20 +16,25 @@ import com.launchdarkly.sdk.internal.events.DiagnosticStore; import com.launchdarkly.sdk.internal.fdv2.payloads.FDv2Event; import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ProtocolHandler; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.internal.http.HttpHelpers; import com.launchdarkly.sdk.internal.http.HttpProperties; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.SelectorSource; import com.launchdarkly.sdk.server.datasources.Synchronizer; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; +import com.launchdarkly.sdk.fdv2.ChangeSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import com.launchdarkly.sdk.server.subsystems.SerializationException; import com.google.gson.stream.JsonReader; import okhttp3.Headers; import org.jetbrains.annotations.NotNull; import java.io.Reader; +import java.util.Map; import java.net.URI; import java.time.Duration; import java.time.Instant; @@ -268,7 +273,7 @@ private void handleMessage(MessageEvent event) { case CHANGESET: FDv2ProtocolHandler.FDv2ActionChangeset changeset = (FDv2ProtocolHandler.FDv2ActionChangeset) action; try { - DataStoreTypes.ChangeSet converted = + ChangeSet>>> converted = FDv2ChangeSetTranslator.toChangeSet( changeset.getChangeset(), logger, diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/WriteThroughStore.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/WriteThroughStore.java index df6cfd18..44a3d3d0 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/WriteThroughStore.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/WriteThroughStore.java @@ -1,10 +1,10 @@ package com.launchdarkly.sdk.server; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider.CacheStats; import com.launchdarkly.sdk.server.subsystems.DataStore; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; @@ -13,6 +13,7 @@ import com.launchdarkly.sdk.server.subsystems.TransactionalDataStore; import java.io.IOException; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -104,7 +105,7 @@ public CacheStats getCacheStats() { } @Override - public void apply(ChangeSet changeSet) { + public void apply(ChangeSet>>> changeSet) { txMemoryStore.apply(changeSet); maybeSwitchStore(); @@ -157,7 +158,7 @@ private void maybeSwitchStore() { * @param sortedChangeSet the change set to apply (data will have been sorted by data source updates) * @return true if the operation succeeded, false otherwise */ - private boolean applyToLegacyPersistence(ChangeSet sortedChangeSet) { + private boolean applyToLegacyPersistence(ChangeSet>>> sortedChangeSet) { // Data will have been sorted by data source updates. switch (sortedChangeSet.getType()) { case Full: @@ -176,7 +177,7 @@ private boolean applyToLegacyPersistence(ChangeSet sortedChangeS /** * Applies a full change set to a legacy persistent store. */ - private void applyFullChangeSetToLegacyStore(ChangeSet sortedChangeSet) { + private void applyFullChangeSetToLegacyStore(ChangeSet>>> sortedChangeSet) { // Preserve shouldPersist flag when converting ChangeSet to FullDataSet persistentStore.init(new FullDataSet<>(sortedChangeSet.getData(), sortedChangeSet.shouldPersist())); } @@ -187,7 +188,7 @@ private void applyFullChangeSetToLegacyStore(ChangeSet sortedCha * @param sortedChangeSet the change set to apply * @return true if all operations succeeded, false otherwise */ - private boolean applyPartialChangeSetToLegacyStore(ChangeSet sortedChangeSet) { + private boolean applyPartialChangeSetToLegacyStore(ChangeSet>>> sortedChangeSet) { for (java.util.Map.Entry> kindItemsPair : sortedChangeSet.getData()) { for (java.util.Map.Entry item : kindItemsPair.getValue().getItems()) { boolean applySuccess = persistentStore.upsert(kindItemsPair.getKey(), item.getKey(), item.getValue()); diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java index 6b241094..32b6c72b 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java @@ -1,9 +1,16 @@ package com.launchdarkly.sdk.server.datasources; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import java.io.Closeable; +import java.util.Map; import java.util.function.Function; /** @@ -14,49 +21,15 @@ */ public class FDv2SourceResult implements Closeable { - public enum State { - /** - * The data source has encountered an interruption and will attempt to reconnect. This isn't intended to be used - * with an initializer, and instead TERMINAL_ERROR should be used. When this status is used with an initializer, - * it will still be a terminal state. - */ - INTERRUPTED, - /** - * The data source has been shut down and will not produce any further results. - */ - SHUTDOWN, - /** - * The data source has encountered a terminal error and will not produce any further results. - */ - TERMINAL_ERROR, - /** - * The data source has been instructed to disconnect and will not produce any further results. - */ - GOODBYE, - } - - public enum ResultType { - /** - * The source has emitted a change set. This implies that the source is valid. - */ - CHANGE_SET, - /** - * The source is emitting a status which indicates a transition from being valid to being in some kind - * of error state. The source will emit a CHANGE_SET if it becomes valid again. - */ - STATUS, - } - /** * Represents a change in the status of the source. */ public static class Status { - private final State state; + private final SourceSignal state; private final DataSourceStatusProvider.ErrorInfo errorInfo; - private final String reason; - public State getState() { + public SourceSignal getState() { return state; } @@ -64,26 +37,26 @@ public DataSourceStatusProvider.ErrorInfo getErrorInfo() { return errorInfo; } - Status(State state, DataSourceStatusProvider.ErrorInfo errorInfo, String reason) { + Status(SourceSignal state, DataSourceStatusProvider.ErrorInfo errorInfo, String reason) { this.state = state; this.errorInfo = errorInfo; this.reason = reason; } public static Status goodbye(String reason) { - return new Status(State.GOODBYE, null, reason); + return new Status(SourceSignal.GOODBYE, null, reason); } public static Status interrupted(DataSourceStatusProvider.ErrorInfo errorInfo) { - return new Status(State.INTERRUPTED, errorInfo, null); + return new Status(SourceSignal.INTERRUPTED, errorInfo, null); } public static Status terminalError(DataSourceStatusProvider.ErrorInfo errorInfo) { - return new Status(State.TERMINAL_ERROR, errorInfo, null); + return new Status(SourceSignal.TERMINAL_ERROR, errorInfo, null); } public static Status shutdown() { - return new Status(State.SHUTDOWN, null, null); + return new Status(SourceSignal.SHUTDOWN, null, null); } /** @@ -95,18 +68,15 @@ public String getReason() { } } - private final DataStoreTypes.ChangeSet changeSet; + private final ChangeSet>>> changeSet; private final Status status; - - private final ResultType resultType; - + private final SourceResultType resultType; private final boolean fdv1Fallback; - private final Function completionCallback; private FDv2SourceResult( - DataStoreTypes.ChangeSet changeSet, - Status status, ResultType resultType, + ChangeSet>>> changeSet, + Status status, SourceResultType resultType, boolean fdv1Fallback, Function completionCallback ) { @@ -125,7 +95,7 @@ public static FDv2SourceResult interrupted(DataSourceStatusProvider.ErrorInfo er return new FDv2SourceResult( null, Status.interrupted(errorInfo), - ResultType.STATUS, + SourceResultType.STATUS, fdv1Fallback, completionCallback); } @@ -137,7 +107,7 @@ public static FDv2SourceResult shutdown() { public static FDv2SourceResult shutdown(Function completionCallback) { return new FDv2SourceResult(null, Status.shutdown(), - ResultType.STATUS, + SourceResultType.STATUS, false, completionCallback); } @@ -149,20 +119,20 @@ public static FDv2SourceResult terminalError(DataSourceStatusProvider.ErrorInfo public static FDv2SourceResult terminalError(DataSourceStatusProvider.ErrorInfo errorInfo, boolean fdv1Fallback, Function completionCallback) { return new FDv2SourceResult(null, Status.terminalError(errorInfo), - ResultType.STATUS, + SourceResultType.STATUS, fdv1Fallback, completionCallback); } - public static FDv2SourceResult changeSet(DataStoreTypes.ChangeSet changeSet, boolean fdv1Fallback) { + public static FDv2SourceResult changeSet(ChangeSet>>> changeSet, boolean fdv1Fallback) { return changeSet(changeSet, fdv1Fallback, null); } - public static FDv2SourceResult changeSet(DataStoreTypes.ChangeSet changeSet, boolean fdv1Fallback, Function completionCallback) { + public static FDv2SourceResult changeSet(ChangeSet>>> changeSet, boolean fdv1Fallback, Function completionCallback) { return new FDv2SourceResult( changeSet, null, - ResultType.CHANGE_SET, + SourceResultType.CHANGE_SET, fdv1Fallback, completionCallback); } @@ -175,12 +145,12 @@ public static FDv2SourceResult goodbye(String reason, boolean fdv1Fallback, Func return new FDv2SourceResult( null, Status.goodbye(reason), - ResultType.STATUS, + SourceResultType.STATUS, fdv1Fallback, completionCallback); } - public ResultType getResultType() { + public SourceResultType getResultType() { return resultType; } @@ -188,7 +158,7 @@ public Status getStatus() { return status; } - public DataStoreTypes.ChangeSet getChangeSet() { + public ChangeSet>>> getChangeSet() { return changeSet; } @@ -218,7 +188,7 @@ public FDv2SourceResult withCompletion(Function newCallback) { @Override public void close() { - if(completionCallback != null) { + if (completionCallback != null) { completionCallback.apply(null); } } diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/SelectorSource.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/SelectorSource.java index 163c384e..a3d8b90f 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/SelectorSource.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/SelectorSource.java @@ -1,6 +1,6 @@ package com.launchdarkly.sdk.server.datasources; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; /** * This type is currently experimental and not subject to semantic versioning. diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceBase.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceBase.java index 38b807cf..85086d8b 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceBase.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceBase.java @@ -3,7 +3,7 @@ import com.google.common.collect.ImmutableList; import com.launchdarkly.logging.LDLogger; import com.launchdarkly.sdk.LDValue; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.integrations.FileDataSourceBuilder.SourceInfo; import com.launchdarkly.sdk.server.integrations.FileDataSourceParsing.FileDataException; @@ -12,8 +12,8 @@ import com.launchdarkly.sdk.server.integrations.FileDataSourceParsing.FlagFileRep; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider.ErrorInfo; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider.ErrorKind; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; @@ -78,14 +78,14 @@ protected FDv2SourceResult loadData() { } Iterable>> data = builder.build(); - ChangeSet changeSet = buildChangeSet(data); + ChangeSet>>> changeSet = buildChangeSet(data); return FDv2SourceResult.changeSet(changeSet, false); } /** * Builds a ChangeSet from the data entries. */ - private ChangeSet buildChangeSet(Iterable>> data) { + private ChangeSet>>> buildChangeSet(Iterable>> data) { return new ChangeSet<>( ChangeSetType.Full, // File data is currently selector-less. diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceImpl.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceImpl.java index 718dd90b..348919eb 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceImpl.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileDataSourceImpl.java @@ -2,6 +2,8 @@ import com.launchdarkly.logging.LDLogger; import com.launchdarkly.logging.LogValues; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.integrations.FileDataSourceBuilder.SourceInfo; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider.State; @@ -78,8 +80,8 @@ private void runUpdateLoop() { if (closed.get()) { break; } - if (result.getResultType() == FDv2SourceResult.ResultType.STATUS && - result.getStatus().getState() == FDv2SourceResult.State.SHUTDOWN) { + if (result.getResultType() == SourceResultType.STATUS && + result.getStatus().getState() == SourceSignal.SHUTDOWN) { break; } processResult(result); @@ -92,7 +94,7 @@ private void runUpdateLoop() { } private void processResult(FDv2SourceResult result) { - if (result.getResultType() == FDv2SourceResult.ResultType.CHANGE_SET) { + if (result.getResultType() == SourceResultType.CHANGE_SET) { // Convert ChangeSet to FullDataSet for legacy init() FullDataSet fullData = new FullDataSet<>( result.getChangeSet().getData(), @@ -101,9 +103,9 @@ private void processResult(FDv2SourceResult result) { dataSourceUpdates.init(fullData); dataSourceUpdates.updateStatus(State.VALID, null); inited.set(true); - } else if (result.getResultType() == FDv2SourceResult.ResultType.STATUS) { + } else if (result.getResultType() == SourceResultType.STATUS) { // Handle error/status results - if (result.getStatus().getState() != FDv2SourceResult.State.SHUTDOWN) { + if (result.getStatus().getState() != SourceSignal.SHUTDOWN) { dataSourceUpdates.updateStatus(State.INTERRUPTED, result.getStatus().getErrorInfo()); } // No terminal errors/shutdown for this adaptation. diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileInitializer.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileInitializer.java index f7a7b03e..2b336902 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileInitializer.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/FileInitializer.java @@ -1,6 +1,8 @@ package com.launchdarkly.sdk.server.integrations; import com.launchdarkly.logging.LDLogger; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.Initializer; import com.launchdarkly.sdk.server.integrations.FileDataSourceBuilder.SourceInfo; @@ -36,8 +38,8 @@ public CompletableFuture run() { return synchronizer.next().thenApply(result -> { // Convert INTERRUPTED to TERMINAL_ERROR for initializer semantics // (initializers can't retry, so all errors are terminal) - if (result.getResultType() == FDv2SourceResult.ResultType.STATUS && - result.getStatus().getState() == FDv2SourceResult.State.INTERRUPTED) { + if (result.getResultType() == SourceResultType.STATUS && + result.getStatus().getState() == SourceSignal.INTERRUPTED) { return FDv2SourceResult.terminalError( result.getStatus().getErrorInfo(), result.isFdv1Fallback() diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/TestDataV2.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/TestDataV2.java index 21af15fc..aea4aaf8 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/TestDataV2.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/TestDataV2.java @@ -2,15 +2,16 @@ import com.google.common.collect.ImmutableMap; import com.launchdarkly.sdk.internal.collections.IterableAsyncQueue; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.DataModel; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.Synchronizer; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; import com.launchdarkly.sdk.server.subsystems.DataSourceBuildInputs; import com.launchdarkly.sdk.server.subsystems.DataSourceBuilder; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import java.time.Instant; @@ -254,7 +255,7 @@ private void pushToSynchronizers(FDv2SourceResult result) { } } - private ChangeSet makeFullChangeSet() { + private ChangeSet>>> makeFullChangeSet() { ImmutableMap copiedData; synchronized (lock) { copiedData = ImmutableMap.copyOf(currentFlags); @@ -269,7 +270,7 @@ private ChangeSet makeFullChangeSet() { shouldPersist); } - private ChangeSet makePartialChangeSet(String key, ItemDescriptor item) { + private ChangeSet>>> makePartialChangeSet(String key, ItemDescriptor item) { return new ChangeSet<>( ChangeSetType.Partial, Selector.EMPTY, diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/DataStoreTypes.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/DataStoreTypes.java index c98e0ff2..0667bf4e 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/DataStoreTypes.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/DataStoreTypes.java @@ -1,7 +1,7 @@ package com.launchdarkly.sdk.server.subsystems; import com.google.common.collect.ImmutableList; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import java.util.Map; import java.util.Objects; @@ -360,133 +360,4 @@ public int hashCode() { } } - /** - * Enumeration that indicates if this change is a full or partial change. - *

- * This class is not stable, and not subject to any backwards compatibility guarantees or semantic versioning. - * It is in early access. If you want access to this feature please join the EAP. https://launchdarkly.com/docs/sdk/features/data-saving-mode - *

- */ - public enum ChangeSetType { - /** - * Represents a full store configuration which replaces all data currently in the store. - */ - Full, - - /** - * Represents an incremental set of changes to be applied to the existing data in the store. - */ - Partial, - - /** - * Indicates that there are no store changes. - */ - None - } - - /** - * Represents a set of changes to apply to a store. - *

- * This class is not stable, and not subject to any backwards compatibility guarantees or semantic versioning. - * It is in early access. If you want access to this feature please join the EAP. https://launchdarkly.com/docs/sdk/features/data-saving-mode - *

- * - * @param will be {@link ItemDescriptor} or {@link SerializedItemDescriptor} - */ - public static final class ChangeSet { - private final ChangeSetType type; - private final Selector selector; - private final String environmentId; - private final Iterable>> data; - private final boolean shouldPersist; - - /** - * Returns the type of the changeset. - * - * @return the changeset type - */ - public ChangeSetType getType() { - return type; - } - - /** - * Returns the selector for this change. This selector will not be null, but it can be an empty selector. - * - * @return the selector - */ - public Selector getSelector() { - return selector; - } - - /** - * Returns the environment ID associated with the change. This may not always be available, and when it is not, - * the value will be null. - * - * @return the environment ID, or null if not available - */ - public String getEnvironmentId() { - return environmentId; - } - - /** - * Returns a list of changes. - * - * @return an enumeration of key-value pairs; may be empty, but will not be null - */ - public Iterable>> getData() { - return data; - } - - /** - * Returns whether this data should be persisted to persistent stores. - *

- * If true, indicates that the data should be propagated to any connected - * persistent stores. If false, indicates that the data should not be persisted (e.g., data from - * an untrusted source like a file cache). - * - * @return true if the data should be persisted, false otherwise - */ - public boolean shouldPersist() { - return shouldPersist; - } - - /** - * Constructs a new ChangeSet instance. - * - * @param type the type of the changeset - * @param selector the selector for this change - * @param data the list of changes - * @param environmentId the environment ID, or null if not available - * @param shouldPersist true if the data should be persisted to persistent stores, false otherwise - */ - public ChangeSet(ChangeSetType type, Selector selector, - Iterable>> data, String environmentId, boolean shouldPersist) { - this.type = type; - this.selector = selector; - this.data = data == null ? ImmutableList.of() : data; - this.environmentId = environmentId; - this.shouldPersist = shouldPersist; - } - - @Override - public boolean equals(Object o) { - if (o instanceof ChangeSet) { - ChangeSet other = (ChangeSet)o; - return type == other.type && Objects.equals(selector, other.selector) && - Objects.equals(environmentId, other.environmentId) && Objects.equals(data, other.data) && - shouldPersist == other.shouldPersist; - } - return false; - } - - @Override - public int hashCode() { - return Objects.hash(type, selector, environmentId, data, shouldPersist); - } - - @Override - public String toString() { - return "ChangeSet(" + type + "," + selector + "," + environmentId + "," + data + "," + shouldPersist + ")"; - } - } } diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataSourceUpdateSink.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataSourceUpdateSink.java index a4e9b8d7..85f2ba78 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataSourceUpdateSink.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataSourceUpdateSink.java @@ -1,7 +1,11 @@ package com.launchdarkly.sdk.server.subsystems; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; + +import java.util.Map; /** * Interface that an implementation of {@link DataSource} will use to push data into the SDK transactionally. @@ -27,6 +31,5 @@ public interface TransactionalDataSourceUpdateSink { * @param changeSet the changeset to apply * @return true if the update succeeded, false if it failed */ - boolean apply(ChangeSet changeSet); + boolean apply(ChangeSet>>> changeSet); } - diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataStore.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataStore.java index 5b84c3ea..62339f05 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataStore.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/subsystems/TransactionalDataStore.java @@ -1,8 +1,12 @@ package com.launchdarkly.sdk.server.subsystems; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.Selector; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; + +import java.util.Map; /** * Interface for a data store that holds feature flags and related data received by the SDK. @@ -26,7 +30,7 @@ public interface TransactionalDataStore { * * @param changeSet the changeset to apply */ - void apply(ChangeSet changeSet); + void apply(ChangeSet>>> changeSet); /** * Returns the selector for the currently stored data. The selector will be non-null but may be empty. diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataModelDependenciesTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataModelDependenciesTest.java index a6f8777b..2fb2a962 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataModelDependenciesTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataModelDependenciesTest.java @@ -8,13 +8,13 @@ import com.launchdarkly.sdk.server.DataModel.FeatureFlag; import com.launchdarkly.sdk.server.DataModel.Operator; import com.launchdarkly.sdk.server.DataModel.Segment; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.DataModelDependencies.DependencyTracker; import com.launchdarkly.sdk.server.DataModelDependencies.KindAndKey; import com.launchdarkly.sdk.server.DataStoreTestTypes.DataBuilder; import com.launchdarkly.sdk.server.DataStoreTestTypes.TestItem; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; @@ -392,7 +392,7 @@ public void kindAndKeyEquality() { public void sortChangesetPreservesChangeSetMetadata() { Selector selector = Selector.make(42, "test-state"); String environmentId = "test-env"; - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, selector, ImmutableList.of(), @@ -400,7 +400,7 @@ public void sortChangesetPreservesChangeSetMetadata() { true ); - ChangeSet result = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> result = DataModelDependencies.sortChangeset(changeSet); assertEquals(ChangeSetType.Partial, result.getType()); assertEquals(selector.getVersion(), result.getSelector().getVersion()); @@ -438,7 +438,7 @@ public void sortChangesetSortsPrerequisiteFlagsFirst() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(1, "state1"), changeSetData, @@ -446,7 +446,7 @@ public void sortChangesetSortsPrerequisiteFlagsFirst() { true ); - ChangeSet result = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> result = DataModelDependencies.sortChangeset(changeSet); Map.Entry> flagsData = null; for (Map.Entry> entry: result.getData()) { @@ -487,7 +487,7 @@ public void sortChangesetSortsSegmentsBeforeFlags() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), changeSetData, @@ -495,7 +495,7 @@ public void sortChangesetSortsSegmentsBeforeFlags() { true ); - ChangeSet result = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> result = DataModelDependencies.sortChangeset(changeSet); List kinds = ImmutableList.copyOf(transform(result.getData(), Map.Entry::getKey)); assertEquals(2, kinds.size()); @@ -505,7 +505,7 @@ public void sortChangesetSortsSegmentsBeforeFlags() { @Test public void sortChangesetHandlesEmptyChangeset() { - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), ImmutableList.of(), @@ -513,7 +513,7 @@ public void sortChangesetHandlesEmptyChangeset() { true ); - ChangeSet result = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> result = DataModelDependencies.sortChangeset(changeSet); assertTrue("Result data should be empty", Iterables.isEmpty(result.getData())); assertEquals(ChangeSetType.Full, result.getType()); @@ -542,7 +542,7 @@ public void sortChangesetHandlesMultipleDataKinds() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(1, "state1"), changeSetData, @@ -550,7 +550,7 @@ public void sortChangesetHandlesMultipleDataKinds() { true ); - ChangeSet result = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> result = DataModelDependencies.sortChangeset(changeSet); assertEquals(2, Iterables.size(result.getData())); @@ -583,7 +583,7 @@ public void sortChangesetPreservesDeletedItems() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(1, "state1"), changeSetData, @@ -591,7 +591,7 @@ public void sortChangesetPreservesDeletedItems() { true ); - ChangeSet result = DataModelDependencies.sortChangeset(changeSet); + ChangeSet>>> result = DataModelDependencies.sortChangeset(changeSet); Map.Entry> flagsData = null; for (Map.Entry> entry: result.getData()) { diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapterTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapterTest.java index 8f8f7824..7d88f621 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapterTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceSynchronizerAdapterTest.java @@ -1,5 +1,7 @@ package com.launchdarkly.sdk.server; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.subsystems.DataSource; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSink; @@ -64,8 +66,8 @@ public void closeBeforeInitializationDoesNotLeakThread() throws Exception { // Verify next() completes with shutdown result (should be nearly immediate) FDv2SourceResult result = nextFuture.get(2, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); // Signal the blocked initialization (should already be cancelled/irrelevant) blockInitLatch.countDown(); @@ -99,8 +101,8 @@ public void normalInitializationCompletes() throws Exception { // Verify shutdown result is received FDv2SourceResult result = nextFuture.get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); } /** @@ -121,8 +123,8 @@ public void initializationErrorIsReported() throws Exception { FDv2SourceResult result = nextFuture.get(2, TimeUnit.SECONDS); // Should receive an interrupted status with error info - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertNotNull(result.getStatus().getErrorInfo()); assertTrue(result.getStatus().getErrorInfo().getMessage().contains("Init failed")); @@ -144,8 +146,8 @@ public void closeBeforeStartDoesNotFail() throws Exception { // next() should still work and return shutdown immediately CompletableFuture nextFuture = adapter.next(); FDv2SourceResult result = nextFuture.get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); } /** @@ -164,8 +166,8 @@ public void rapidCloseDoesNotCauseIssues() throws Exception { adapter.close(); FDv2SourceResult result = nextFuture.get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); blockLatch.countDown(); } diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceUpdatesImplTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceUpdatesImplTest.java index 1431970e..5df085f7 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceUpdatesImplTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DataSourceUpdatesImplTest.java @@ -2,7 +2,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.DataModel.FeatureFlag; import com.launchdarkly.sdk.server.DataModel.Segment; import com.launchdarkly.sdk.server.DataStoreTestTypes.DataBuilder; @@ -13,8 +13,8 @@ import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider.Status; import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider; import com.launchdarkly.sdk.server.subsystems.DataStore; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; @@ -119,7 +119,7 @@ private static Segment nextVersion(Segment segment) { return segmentBuilder(segment.getKey()).version(segment.getVersion() + 1).build(); } - private static ChangeSet makeFullChangeSet(FeatureFlag... flags) { + private static ChangeSet>>> makeFullChangeSet(FeatureFlag... flags) { List>> data = new ArrayList<>(); if (flags.length > 0) { Map flagItems = new HashMap<>(); @@ -140,7 +140,7 @@ private static ChangeSet makeFullChangeSet(FeatureFlag... flags) ); } - private static ChangeSet makePartialChangeSet(FeatureFlag... flags) { + private static ChangeSet>>> makePartialChangeSet(FeatureFlag... flags) { List>> data = new ArrayList<>(); if (flags.length > 0) { Map flagItems = new HashMap<>(); @@ -705,7 +705,7 @@ public void applyPartialChangeSetSendsEventForDeletedFlag() throws Exception { new KeyedItems<>(ImmutableList.copyOf(flagItems.entrySet())) ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(1, "state1"), data, @@ -833,7 +833,7 @@ public void applyFullChangeSetSendsEventsForFlagsWhoseSegmentsChanged() throws E kindEntry.getValue() )); } - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), changeSetData, @@ -886,7 +886,7 @@ public void applyPartialChangeSetSendsEventsForFlagsWhoseSegmentsChanged() throw new KeyedItems<>(ImmutableList.copyOf(segmentItems.entrySet())) ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(1, "state1"), segmentData, @@ -1025,7 +1025,7 @@ public void applyFullChangeSetToLegacyStoreWithEnvironmentId() throws Exception new KeyedItems<>(ImmutableList.copyOf(flagItems.entrySet())) ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), data, diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DefaultFDv2RequestorTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DefaultFDv2RequestorTest.java index d3e1cfed..808606f4 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DefaultFDv2RequestorTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/DefaultFDv2RequestorTest.java @@ -1,7 +1,7 @@ package com.launchdarkly.sdk.server; import com.launchdarkly.sdk.internal.fdv2.payloads.FDv2Event; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.internal.http.HttpErrors; import com.launchdarkly.sdk.internal.http.HttpProperties; import com.launchdarkly.sdk.server.subsystems.ClientContext; diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslatorTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslatorTest.java index 0f5b3bdf..4bf60cbc 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslatorTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2ChangeSetTranslatorTest.java @@ -9,10 +9,12 @@ import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ChangeSet.FDv2Change; import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ChangeSet.FDv2ChangeSetType; import com.launchdarkly.sdk.internal.fdv2.sources.FDv2ChangeSet.FDv2ChangeType; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import org.junit.Test; @@ -58,7 +60,7 @@ public void toChangeSet_withFullChangeset_returnsFullChangeSetType() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(ChangeSetType.Full, result.getType()); @@ -71,7 +73,7 @@ public void toChangeSet_withPartialChangeset_returnsPartialChangeSetType() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.PARTIAL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(ChangeSetType.Partial, result.getType()); @@ -82,7 +84,7 @@ public void toChangeSet_withNoneChangeset_returnsNoneChangeSetType() { List changes = ImmutableList.of(); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.NONE, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(ChangeSetType.None, result.getType()); @@ -94,7 +96,7 @@ public void toChangeSet_includesSelector() { Selector selector = Selector.make(42, "test-state"); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, selector); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(selector.getVersion(), result.getSelector().getVersion()); @@ -106,7 +108,7 @@ public void toChangeSet_includesEnvironmentId() { List changes = ImmutableList.of(); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, "test-env-id", true); assertEquals("test-env-id", result.getEnvironmentId()); @@ -117,7 +119,7 @@ public void toChangeSet_withNullEnvironmentId_returnsNullEnvironmentId() { List changes = ImmutableList.of(); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertNull(result.getEnvironmentId()); @@ -130,12 +132,12 @@ public void toChangeSet_withPutOperation_deserializesItem() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); - Map.Entry> flagData = findDataKind(result, "features"); + Map.Entry> flagData = findDataKind(result, "features"); assertNotNull(flagData); - Map.Entry item = getFirstItem(flagData.getValue()); + Map.Entry item = getFirstItem(flagData.getValue()); assertEquals("flag1", item.getKey()); assertNotNull(item.getValue().getItem()); assertEquals(1, item.getValue().getVersion()); @@ -148,12 +150,12 @@ public void toChangeSet_withDeleteOperation_createsDeletedDescriptor() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.PARTIAL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); - Map.Entry> flagData = findDataKind(result, "features"); + Map.Entry> flagData = findDataKind(result, "features"); assertNotNull(flagData); - Map.Entry item = getFirstItem(flagData.getValue()); + Map.Entry item = getFirstItem(flagData.getValue()); assertEquals("flag1", item.getKey()); assertNull(item.getValue().getItem()); assertEquals(5, item.getValue().getVersion()); @@ -167,10 +169,10 @@ public void toChangeSet_withMultipleFlags_groupsByKind() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); - Map.Entry> flagData = findDataKind(result, "features"); + Map.Entry> flagData = findDataKind(result, "features"); assertNotNull(flagData); assertEquals(2, countItems(flagData.getValue())); } @@ -183,7 +185,7 @@ public void toChangeSet_withFlagsAndSegments_createsMultipleDataKinds() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(2, countDataKinds(result)); @@ -199,7 +201,7 @@ public void toChangeSet_withUnknownKind_skipsItemAndLogsWarning() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(1, countDataKinds(result)); @@ -215,10 +217,10 @@ public void toChangeSet_withPutOperationMissingObject_skipsItemAndLogsWarning() ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); - Map.Entry> flagData = findDataKind(result, "features"); + Map.Entry> flagData = findDataKind(result, "features"); assertNotNull(flagData); assertEquals(1, countItems(flagData.getValue())); assertEquals("flag2", getFirstItem(flagData.getValue()).getKey()); @@ -230,7 +232,7 @@ public void toChangeSet_withEmptyChanges_returnsEmptyData() { List changes = ImmutableList.of(); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(0, countDataKinds(result)); @@ -245,24 +247,24 @@ public void toChangeSet_withMixedPutAndDelete_handlesAllOperations() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.PARTIAL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); assertEquals(2, countDataKinds(result)); - Map.Entry> flagData = findDataKind(result, "features"); + Map.Entry> flagData = findDataKind(result, "features"); assertNotNull(flagData); assertEquals(2, countItems(flagData.getValue())); - Map.Entry flag1 = findItem(flagData.getValue(), "flag1"); + Map.Entry flag1 = findItem(flagData.getValue(), "flag1"); assertNotNull(flag1.getValue().getItem()); assertEquals(1, flag1.getValue().getVersion()); - Map.Entry flag2 = findItem(flagData.getValue(), "flag2"); + Map.Entry flag2 = findItem(flagData.getValue(), "flag2"); assertNull(flag2.getValue().getItem()); assertEquals(2, flag2.getValue().getVersion()); - Map.Entry> segmentData = findDataKind(result, "segments"); + Map.Entry> segmentData = findDataKind(result, "segments"); assertNotNull(segmentData); assertEquals(1, countItems(segmentData.getValue())); } @@ -276,12 +278,12 @@ public void toChangeSet_preservesOrderOfChangesWithinKind() { ); FDv2ChangeSet fdv2ChangeSet = new FDv2ChangeSet(FDv2ChangeSetType.FULL, changes, Selector.make(1, "state1")); - DataStoreTypes.ChangeSet result = + ChangeSet>>> result = FDv2ChangeSetTranslator.toChangeSet(fdv2ChangeSet, testLogger, null, true); - Map.Entry> flagData = findDataKind(result, "features"); + Map.Entry> flagData = findDataKind(result, "features"); assertNotNull(flagData); - List> items = toList(flagData.getValue().getItems()); + List> items = toList(flagData.getValue().getItems()); assertEquals("flag3", items.get(0).getKey()); assertEquals("flag1", items.get(1).getKey()); assertEquals("flag2", items.get(2).getKey()); @@ -289,9 +291,9 @@ public void toChangeSet_preservesOrderOfChangesWithinKind() { // Helper methods - private Map.Entry> findDataKind( - DataStoreTypes.ChangeSet changeSet, String kindName) { - for (Map.Entry> entry : changeSet.getData()) { + private Map.Entry> findDataKind( + ChangeSet>>> changeSet, String kindName) { + for (Map.Entry> entry : changeSet.getData()) { if (entry.getKey().getName().equals(kindName)) { return entry; } @@ -299,14 +301,14 @@ private Map.Entry> findDataK return null; } - private Map.Entry getFirstItem( - KeyedItems keyedItems) { + private Map.Entry getFirstItem( + KeyedItems keyedItems) { return keyedItems.getItems().iterator().next(); } - private Map.Entry findItem( - KeyedItems keyedItems, String key) { - for (Map.Entry entry : keyedItems.getItems()) { + private Map.Entry findItem( + KeyedItems keyedItems, String key) { + for (Map.Entry entry : keyedItems.getItems()) { if (entry.getKey().equals(key)) { return entry; } @@ -314,26 +316,26 @@ private Map.Entry findItem( return null; } - private int countItems(KeyedItems keyedItems) { + private int countItems(KeyedItems keyedItems) { int count = 0; - for (@SuppressWarnings("unused") Map.Entry entry : keyedItems.getItems()) { + for (@SuppressWarnings("unused") Map.Entry entry : keyedItems.getItems()) { count++; } return count; } - private int countDataKinds(DataStoreTypes.ChangeSet changeSet) { + private int countDataKinds(ChangeSet>>> changeSet) { int count = 0; - for (@SuppressWarnings("unused") Map.Entry> entry : changeSet.getData()) { + for (@SuppressWarnings("unused") Map.Entry> entry : changeSet.getData()) { count++; } return count; } - private List> toList( - Iterable> items) { - List> list = new ArrayList<>(); - for (Map.Entry item : items) { + private List> toList( + Iterable> items) { + List> list = new ArrayList<>(); + for (Map.Entry item : items) { list.add(item); } return list; diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceFallbackConditionTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceFallbackConditionTest.java index 8297f5b9..94bcf3bf 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceFallbackConditionTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceFallbackConditionTest.java @@ -1,13 +1,20 @@ package com.launchdarkly.sdk.server; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.FDv2DataSourceConditions.Condition; import com.launchdarkly.sdk.server.FDv2DataSourceConditions.FallbackCondition; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import org.junit.After; +import java.util.Map; + import org.junit.Test; import java.time.Instant; @@ -32,9 +39,9 @@ public void tearDown() { } } - private DataStoreTypes.ChangeSet makeChangeSet() { - return new DataStoreTypes.ChangeSet<>( - DataStoreTypes.ChangeSetType.None, + private ChangeSet>>> makeChangeSet() { + return new ChangeSet<>( + ChangeSetType.None, Selector.EMPTY, null, null, @@ -103,7 +110,7 @@ public void changeSetCancelsActiveTimer() throws Exception { ); // Cancel timer with CHANGE_SET - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); // Wait longer than the timeout period @@ -121,7 +128,7 @@ public void changeSetWithoutActiveTimerDoesNothing() throws Exception { CompletableFuture resultFuture = condition.execute(); // Inform with CHANGE_SET without starting a timer first - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); // Wait to ensure nothing happens @@ -279,7 +286,7 @@ public void timerCanBeStartedAfterBeingCancelled() throws Exception { ); // Cancel timer with CHANGE_SET - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); // Start timer again @@ -318,7 +325,7 @@ public void changeSetAfterTimerFiresDoesNotAffectCompletedFuture() throws Except assertSame(condition, result); // Inform with CHANGE_SET after timer has fired - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); // Future should remain complete @@ -378,7 +385,7 @@ public void changeSetDuringTimerExecutionCancelsTimer() throws Exception { Thread.sleep(500); // Cancel with CHANGE_SET - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); // Wait past the original timeout @@ -404,7 +411,7 @@ public void multipleChangeSetCallsWithActiveTimerAreHandled() throws Exception { ); // Cancel with multiple CHANGE_SETs - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceRecoveryConditionTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceRecoveryConditionTest.java index 6910db31..b3878bad 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceRecoveryConditionTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceRecoveryConditionTest.java @@ -1,16 +1,22 @@ package com.launchdarkly.sdk.server; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.FDv2DataSourceConditions.Condition; import com.launchdarkly.sdk.server.FDv2DataSourceConditions.RecoveryCondition; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import org.junit.After; import org.junit.Test; import java.time.Instant; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -33,9 +39,9 @@ public void tearDown() { } } - private DataStoreTypes.ChangeSet makeChangeSet() { - return new DataStoreTypes.ChangeSet<>( - DataStoreTypes.ChangeSetType.None, + private ChangeSet>>> makeChangeSet() { + return new ChangeSet<>( + ChangeSetType.None, Selector.EMPTY, null, null, @@ -125,7 +131,7 @@ public void informWithChangeSetDoesNothing() throws Exception { CompletableFuture resultFuture = condition.execute(); // Inform with CHANGE_SET - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); // Timer should still fire after timeout (inform does nothing) @@ -232,7 +238,7 @@ public void multipleInformCallsDoNotAffectTimer() throws Exception { CompletableFuture resultFuture = condition.execute(); // Multiple inform calls - DataStoreTypes.ChangeSet changeSet = makeChangeSet(); + ChangeSet>>> changeSet = makeChangeSet(); condition.inform(FDv2SourceResult.changeSet(changeSet, false)); condition.inform( FDv2SourceResult.interrupted( diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceTest.java index 2e072282..68acf202 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceTest.java @@ -4,15 +4,22 @@ import com.launchdarkly.logging.LDLogger; import com.launchdarkly.logging.Logs; import com.launchdarkly.sdk.internal.collections.IterableAsyncQueue; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.Initializer; import com.launchdarkly.sdk.server.datasources.Synchronizer; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSinkV2; +import java.util.Map; + import org.junit.After; import org.junit.Test; @@ -48,10 +55,10 @@ public void tearDown() { resourcesToClose.clear(); } - private DataStoreTypes.ChangeSet makeChangeSet(boolean withSelector) { + private ChangeSet>>> makeChangeSet(boolean withSelector) { Selector selector = withSelector ? Selector.make(1, "test-state") : Selector.EMPTY; - return new DataStoreTypes.ChangeSet<>( - DataStoreTypes.ChangeSetType.None, + return new ChangeSet<>( + ChangeSetType.None, selector, null, null, @@ -2676,14 +2683,14 @@ public void fdv1FallbackOnlyCalledOncePerDataSource() throws Exception { private static class MockDataSourceUpdateSink implements DataSourceUpdateSinkV2 { private final AtomicInteger applyCount = new AtomicInteger(0); - private final AtomicReference> lastChangeSet = new AtomicReference<>(); + private final AtomicReference>>>> lastChangeSet = new AtomicReference<>(); private final BlockingQueue applySignals = new LinkedBlockingQueue<>(); private final AtomicReference lastState = new AtomicReference<>(); private final AtomicReference lastError = new AtomicReference<>(); private final BlockingQueue statusUpdates = new LinkedBlockingQueue<>(); @Override - public boolean apply(DataStoreTypes.ChangeSet changeSet) { + public boolean apply(ChangeSet>>> changeSet) { applyCount.incrementAndGet(); lastChangeSet.set(changeSet); applySignals.offer(true); @@ -2706,7 +2713,7 @@ public int getApplyCount() { return applyCount.get(); } - public DataStoreTypes.ChangeSet getLastChangeSet() { + public ChangeSet>>> getLastChangeSet() { return lastChangeSet.get(); } diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/InMemoryDataStoreTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/InMemoryDataStoreTest.java index a784936c..68b9dd95 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/InMemoryDataStoreTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/InMemoryDataStoreTest.java @@ -2,10 +2,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.subsystems.DataStore; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; @@ -83,7 +83,7 @@ public void applyWithFullChangeSetReplacesAllData() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), changeSetData, @@ -107,7 +107,7 @@ public void applyWithFullChangeSetReplacesAllData() { @Test public void applyWithFullChangeSetSetsSelector() { Selector selector = Selector.make(42, "test-state"); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, selector, ImmutableList.of(), @@ -125,7 +125,7 @@ public void applyWithFullChangeSetSetsSelector() { public void applyWithFullChangeSetMarksStoreAsInitialized() { assertFalse(store.isInitialized()); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), ImmutableList.of(), @@ -159,7 +159,7 @@ public void applyWithPartialChangeSetAddsNewItems() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData, @@ -202,7 +202,7 @@ public void applyWithPartialChangeSetCanReplaceItems() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData, @@ -244,7 +244,7 @@ public void applyWithPartialChangeSetCanDeleteItems() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData, @@ -273,7 +273,7 @@ public void applyWithPartialChangeSetUpdatesSelector() { Selector initialSelector = typedStore().getSelector(); Selector newSelector = Selector.make(99, "new-state"); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, newSelector, ImmutableList.of(), @@ -292,7 +292,7 @@ public void applyWithPartialChangeSetUpdatesSelector() { public void applyWithNoneChangeSetDoesNotModifyData() { initStore(); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.None, Selector.make(5, "state5"), ImmutableList.of(), @@ -340,7 +340,7 @@ public void applyWithFullChangeSetHandlesMultipleDataKinds() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), changeSetData, @@ -388,7 +388,7 @@ public void applyWithPartialChangeSetHandlesMultipleDataKinds() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData, @@ -437,7 +437,7 @@ public void applyWithPartialChangeSetPreservesUnaffectedDataKinds() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData, @@ -463,7 +463,7 @@ public void applyWithPartialChangeSetPreservesUnaffectedDataKinds() { public void applyWithFullChangeSetEmptyDataClearsStore() { initStore(); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), ImmutableList.of(), @@ -499,7 +499,7 @@ public void applyWithPartialChangeSetOnUninitializedStore() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(1, "state1"), changeSetData, @@ -539,7 +539,7 @@ public void applyWithMultipleItemsInSameKind() { ) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), changeSetData, @@ -827,7 +827,7 @@ public void exportAllPreservesShouldPersistWhenApplyFalseOverwritesTrue() { new AbstractMap.SimpleEntry<>("key2", new ItemDescriptor(2, item2)) )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -876,7 +876,7 @@ public void exportAllPreservesShouldPersistWhenApplyTrueOverwritesFalse() { new AbstractMap.SimpleEntry<>("key2", new ItemDescriptor(2, item2)) )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -925,7 +925,7 @@ public void exportAllPreservesShouldPersistWhenFullChangeSetOverwrites() { new AbstractMap.SimpleEntry<>("key2", new ItemDescriptor(2, item2)) )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(2, "state2"), changeSetData.entrySet(), diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingInitializerImplTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingInitializerImplTest.java index c22e6f78..efb4c2dd 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingInitializerImplTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingInitializerImplTest.java @@ -1,7 +1,9 @@ package com.launchdarkly.sdk.server; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.internal.http.HttpErrors; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.SelectorSource; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; @@ -92,7 +94,7 @@ public void successfulInitialization() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); verify(requestor, times(1)).Poll(any(Selector.class)); @@ -114,8 +116,8 @@ public void httpRecoverableError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertNotNull(result.getStatus().getErrorInfo()); assertEquals(DataSourceStatusProvider.ErrorKind.ERROR_RESPONSE, result.getStatus().getErrorInfo().getKind()); @@ -138,8 +140,8 @@ public void httpNonRecoverableError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.ERROR_RESPONSE, result.getStatus().getErrorInfo().getKind()); @@ -159,8 +161,8 @@ public void networkError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.NETWORK_ERROR, result.getStatus().getErrorInfo().getKind()); @@ -180,8 +182,8 @@ public void serializationError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.INVALID_DATA, result.getStatus().getErrorInfo().getKind()); @@ -206,8 +208,8 @@ public void shutdownBeforePollCompletes() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); assertNull(result.getStatus().getErrorInfo()); @@ -228,7 +230,7 @@ public void shutdownAfterPollCompletes() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); // Shutdown after completion should still work initializer.close(); @@ -268,8 +270,8 @@ public void errorEventInResponse() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); } @@ -305,8 +307,8 @@ public void goodbyeEventInResponse() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.GOODBYE, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.GOODBYE, result.getStatus().getState()); } @@ -334,8 +336,8 @@ public void emptyEventsArray() throws Exception { // Empty events array should result in terminal error assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); } @@ -389,8 +391,8 @@ public void internalErrorWithInvalidDataKind() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.INVALID_DATA, result.getStatus().getErrorInfo().getKind()); @@ -427,8 +429,8 @@ public void internalErrorWithUnknownKind() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.UNKNOWN, result.getStatus().getErrorInfo().getKind()); @@ -460,7 +462,7 @@ public void fdv1FallbackFlagSetToTrueInSuccessResponse() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(true, result.isFdv1Fallback()); } @@ -479,7 +481,7 @@ public void fdv1FallbackFlagSetToFalseWhenHeaderNotPresent() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(false, result.isFdv1Fallback()); } @@ -503,8 +505,8 @@ public void fdv1FallbackFlagSetToTrueInErrorResponse() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertEquals(true, result.isFdv1Fallback()); } @@ -522,8 +524,8 @@ public void fdv1FallbackFlagSetToFalseInNetworkError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); // Network errors don't have headers, so fallback should be false assertEquals(false, result.isFdv1Fallback()); } @@ -554,7 +556,7 @@ public void environmentIdExtractedFromHeaders() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); assertEquals("test-env-123", result.getChangeSet().getEnvironmentId()); } @@ -574,7 +576,7 @@ public void environmentIdNullWhenHeaderNotPresent() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); assertNull(result.getChangeSet().getEnvironmentId()); } @@ -606,7 +608,7 @@ public void bothFdv1FallbackAndEnvironmentIdExtractedFromHeaders() throws Except FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(true, result.isFdv1Fallback()); assertNotNull(result.getChangeSet()); assertEquals("test-env-456", result.getChangeSet().getEnvironmentId()); diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingSynchronizerImplTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingSynchronizerImplTest.java index da6a9fde..5a8b5e79 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingSynchronizerImplTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/PollingSynchronizerImplTest.java @@ -1,6 +1,8 @@ package com.launchdarkly.sdk.server; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.SelectorSource; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; @@ -108,7 +110,7 @@ public void nextWaitsWhenQueueEmpty() throws Exception { // Now the future should complete FDv2SourceResult result = nextFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); synchronizer.close(); } finally { @@ -144,7 +146,7 @@ public void nextReturnsImmediatelyWhenResultQueued() throws Exception { FDv2SourceResult result = nextFuture.get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); synchronizer.close(); } finally { @@ -177,15 +179,15 @@ public void multipleItemsQueuedReturnedInOrder() throws Exception { // Should have at least 3-4 results queued FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result1.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result1.getResultType()); FDv2SourceResult result2 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result2); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); FDv2SourceResult result3 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result3); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result3.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result3.getResultType()); synchronizer.close(); } finally { @@ -218,8 +220,8 @@ public void shutdownBeforeNextCalled() throws Exception { // next() should return shutdown result FDv2SourceResult result = synchronizer.next().get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); } finally { executor.shutdown(); } @@ -256,8 +258,8 @@ public void shutdownWhileNextWaiting() throws Exception { // next() should complete with shutdown result FDv2SourceResult result = nextFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); } finally { executor.shutdown(); } @@ -298,8 +300,8 @@ public void shutdownAfterMultipleItemsQueued() throws Exception { for (int i = 0; i < 10; i++) { FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - if (result.getResultType() == FDv2SourceResult.ResultType.STATUS && - result.getStatus().getState() == FDv2SourceResult.State.SHUTDOWN) { + if (result.getResultType() == SourceResultType.STATUS && + result.getStatus().getState() == SourceSignal.SHUTDOWN) { gotShutdown = true; break; } @@ -378,19 +380,19 @@ public void errorsInPollingAreSwallowed() throws Exception { // First result should be success FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result1.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result1.getResultType()); // Second result should be the error (INTERRUPTED status) FDv2SourceResult result2 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result2); - assertEquals(FDv2SourceResult.ResultType.STATUS, result2.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result2.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result2.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result2.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.NETWORK_ERROR, result2.getStatus().getErrorInfo().getKind()); // Third result should be success again FDv2SourceResult result3 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result3); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result3.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result3.getResultType()); // Verify polling continued after error assertTrue("Should have at least 2 successful polls", successCount.get() >= 2); @@ -473,7 +475,7 @@ public void nullResponseSwallowedInPolling() throws Exception { // Should get success results - null responses cause exceptions that are swallowed FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); // Verify polling continued after null response assertTrue("Should have successful polls after null", successCount.get() >= 1); @@ -556,8 +558,8 @@ public void nonRecoverableHttpErrorStopsPolling() throws Exception { // First result should be terminal error FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result1.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result1.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.ERROR_RESPONSE, result1.getStatus().getErrorInfo().getKind()); // Wait to see if polling continues @@ -609,14 +611,14 @@ public void recoverableHttpErrorContinuesPolling() throws Exception { // First result should be interrupted error FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result1.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result1.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.ERROR_RESPONSE, result1.getStatus().getErrorInfo().getKind()); // Second result should be success (polling continued) FDv2SourceResult result2 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result2); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); // Verify polling continued after recoverable error assertTrue("Should have at least 2 successful polls after recoverable error", successCount.get() >= 2); @@ -664,17 +666,17 @@ public void multipleRecoverableErrorsContinuePolling() throws Exception { // Get first three interrupted results FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result1.getStatus().getState()); + assertEquals(SourceSignal.INTERRUPTED, result1.getStatus().getState()); FDv2SourceResult result2 = synchronizer.next().get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result2.getStatus().getState()); + assertEquals(SourceSignal.INTERRUPTED, result2.getStatus().getState()); FDv2SourceResult result3 = synchronizer.next().get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result3.getStatus().getState()); + assertEquals(SourceSignal.INTERRUPTED, result3.getStatus().getState()); // Fourth result should be success FDv2SourceResult result4 = synchronizer.next().get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result4.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result4.getResultType()); // Verify polling continued through multiple errors assertTrue("Should have made at least 4 calls", callCount.get() >= 4); @@ -715,7 +717,7 @@ public void nonRecoverableThenRecoverableErrorStopsPolling() throws Exception { // First result should be terminal error FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result1.getStatus().getState()); + assertEquals(SourceSignal.TERMINAL_ERROR, result1.getStatus().getState()); // Wait to ensure no more polling Thread.sleep(200); @@ -793,14 +795,14 @@ public void internalErrorWithInvalidDataKindContinuesPolling() throws Exception // First result should be interrupted with INVALID_DATA error kind FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result1.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result1.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.INVALID_DATA, result1.getStatus().getErrorInfo().getKind()); // Second result should be success (polling continued) FDv2SourceResult result2 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result2); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); // Verify polling continued after internal error assertTrue("Should have made at least 2 calls", callCount.get() >= 2); @@ -857,14 +859,14 @@ public void internalErrorWithUnknownKindContinuesPolling() throws Exception { // First result should be interrupted with UNKNOWN error kind FDv2SourceResult result1 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result1.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result1.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.UNKNOWN, result1.getStatus().getErrorInfo().getKind()); // Second result should be success (polling continued) FDv2SourceResult result2 = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result2); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); // Verify polling continued after internal error assertTrue("Should have made at least 2 calls", callCount.get() >= 2); @@ -908,7 +910,7 @@ public void fdv1FallbackFlagSetToTrueInSuccessResponse() throws Exception { FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(true, result.isFdv1Fallback()); synchronizer.close(); @@ -938,7 +940,7 @@ public void fdv1FallbackFlagSetToFalseWhenHeaderNotPresent() throws Exception { FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(false, result.isFdv1Fallback()); synchronizer.close(); @@ -974,8 +976,8 @@ public void fdv1FallbackFlagSetToTrueInErrorResponse() throws Exception { FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertEquals(true, result.isFdv1Fallback()); synchronizer.close(); @@ -1017,7 +1019,7 @@ public void environmentIdExtractedFromHeaders() throws Exception { FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); assertEquals("test-env-789", result.getChangeSet().getEnvironmentId()); @@ -1061,7 +1063,7 @@ public void bothFdv1FallbackAndEnvironmentIdExtractedFromHeaders() throws Except FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(true, result.isFdv1Fallback()); assertNotNull(result.getChangeSet()); assertEquals("test-env-combined", result.getChangeSet().getEnvironmentId()); diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java index 8b27d2d6..c5b7ca12 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java @@ -2,8 +2,10 @@ import com.launchdarkly.sdk.LDValue; import com.launchdarkly.sdk.internal.events.DiagnosticStore; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.internal.http.HttpProperties; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.SelectorSource; import com.launchdarkly.sdk.server.interfaces.DataSourceStatusProvider; @@ -84,7 +86,7 @@ public void receivesMultipleChangesets() throws Exception { FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result1.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result1.getResultType()); assertNotNull(result1.getChangeSet()); // Second changeset @@ -92,7 +94,7 @@ public void receivesMultipleChangesets() throws Exception { FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); assertNotNull(result2); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); assertNotNull(result2.getChangeSet()); synchronizer.close(); @@ -121,8 +123,8 @@ public void httpNonRecoverableError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.TERMINAL_ERROR, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.TERMINAL_ERROR, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.ERROR_RESPONSE, result.getStatus().getErrorInfo().getKind()); synchronizer.close(); @@ -151,8 +153,8 @@ public void httpRecoverableError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.ERROR_RESPONSE, result.getStatus().getErrorInfo().getKind()); assertNull(result.getStatus().getReason()); @@ -182,8 +184,8 @@ public void networkError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.NETWORK_ERROR, result.getStatus().getErrorInfo().getKind()); synchronizer.close(); @@ -217,8 +219,8 @@ public void invalidEventData() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.INVALID_DATA, result.getStatus().getErrorInfo().getKind()); synchronizer.close(); @@ -255,8 +257,8 @@ public void shutdownBeforeEventReceived() throws Exception { FDv2SourceResult result = nextFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); assertNull(result.getStatus().getErrorInfo()); assertNull(result.getStatus().getReason()); } @@ -292,7 +294,7 @@ public void shutdownAfterEventReceived() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); // Shutdown after receiving event should still work synchronizer.close(); @@ -337,8 +339,8 @@ public void goodbyeEventInResponse() throws Exception { FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); - assertEquals(FDv2SourceResult.State.GOODBYE, result1.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); + assertEquals(SourceSignal.GOODBYE, result1.getStatus().getState()); assertEquals("service-unavailable", result1.getStatus().getReason()); // Second result should be a changeset from the restarted stream @@ -346,7 +348,7 @@ public void goodbyeEventInResponse() throws Exception { FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); assertNotNull(result2); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); assertNotNull(result2.getChangeSet()); // Verify we made 2 requests (initial connection + reconnection after goodbye) @@ -389,7 +391,7 @@ public void heartbeatEvent() throws Exception { // Heartbeat should be ignored, and we should get the changeset assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); synchronizer.close(); @@ -428,7 +430,7 @@ public void selectorWithVersionAndState() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); // Verify selector was fetched when connecting verify(selectorSource, atLeastOnce()).getSelector(); @@ -484,8 +486,8 @@ public void selectorRefetchedOnReconnection() throws Exception { CompletableFuture result1Future = synchronizer.next(); FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); assertNotNull(result1); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result1.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result1.getStatus().getState()); // Keep getting results until we get a CHANGE_SET (reconnection successful) // There may be multiple STATUS results if reconnection takes multiple attempts @@ -494,12 +496,12 @@ public void selectorRefetchedOnReconnection() throws Exception { CompletableFuture resultFuture = synchronizer.next(); FDv2SourceResult result = resultFuture.get(15, TimeUnit.SECONDS); assertNotNull(result); - if (result.getResultType() == FDv2SourceResult.ResultType.CHANGE_SET) { + if (result.getResultType() == SourceResultType.CHANGE_SET) { changesetResult = result; break; } // If it's another STATUS, that's fine, just keep waiting for the changeset - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); + assertEquals(SourceResultType.STATUS, result.getResultType()); } assertNotNull("Should eventually get a CHANGE_SET after reconnection", changesetResult); @@ -547,7 +549,7 @@ public void errorEventFromServer() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); synchronizer.close(); @@ -586,7 +588,7 @@ public void selectorWithVersionOnly() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(1, server.getRecorder().count()); RequestInfo request = server.getRecorder().requireRequest(); @@ -628,7 +630,7 @@ public void selectorWithEmptyState() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(1, server.getRecorder().count()); RequestInfo request = server.getRecorder().requireRequest(); @@ -667,8 +669,8 @@ public void closeCalledMultipleTimes() throws Exception { // next() should still return shutdown FDv2SourceResult result = synchronizer.next().get(1, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.SHUTDOWN, result.getStatus().getState()); } } @@ -701,8 +703,8 @@ public void invalidEventStructureCausesInterrupt() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); synchronizer.close(); } @@ -738,7 +740,7 @@ public void payloadFilterIsAddedToRequest() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); // Verify the request had the filter parameter assertEquals(1, server.getRecorder().count()); @@ -781,7 +783,7 @@ public void payloadFilterWithSelectorBothAddedToRequest() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(1, server.getRecorder().count()); RequestInfo request = server.getRecorder().requireRequest(); @@ -822,7 +824,7 @@ public void emptyPayloadFilterNotAddedToRequest() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); // Verify the request did not have the filter parameter assertEquals(1, server.getRecorder().count()); @@ -863,7 +865,7 @@ public void nullPayloadFilterNotAddedToRequest() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); // Verify the request did not have the filter parameter assertEquals(1, server.getRecorder().count()); @@ -905,7 +907,7 @@ public void fdv1FallbackFlagSetToTrueInSuccessResponse() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(true, result.isFdv1Fallback()); synchronizer.close(); @@ -942,7 +944,7 @@ public void fdv1FallbackFlagSetToFalseWhenHeaderNotPresent() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(false, result.isFdv1Fallback()); synchronizer.close(); @@ -974,8 +976,8 @@ public void fdv1FallbackFlagSetToTrueInErrorResponse() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertEquals(true, result.isFdv1Fallback()); synchronizer.close(); @@ -1013,7 +1015,7 @@ public void environmentIdExtractedFromHeaders() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); assertEquals("test-env-streaming", result.getChangeSet().getEnvironmentId()); @@ -1053,7 +1055,7 @@ public void bothFdv1FallbackAndEnvironmentIdExtractedFromHeaders() throws Except FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertEquals(true, result.isFdv1Fallback()); assertNotNull(result.getChangeSet()); assertEquals("test-env-combined-streaming", result.getChangeSet().getEnvironmentId()); @@ -1092,8 +1094,8 @@ public void serializationExceptionWithoutFallbackHeader() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.INVALID_DATA, result.getStatus().getErrorInfo().getKind()); assertEquals(false, result.isFdv1Fallback()); @@ -1132,8 +1134,8 @@ public void serializationExceptionPreservesFallbackHeader() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.INVALID_DATA, result.getStatus().getErrorInfo().getKind()); assertEquals(true, result.isFdv1Fallback()); @@ -1174,7 +1176,7 @@ public void streamInitDiagnosticRecordedOnSuccessfulChangeset() throws Exception FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); long timeAfterOpen = System.currentTimeMillis(); LDValue event = diagnosticStore.createEventAndReset(0, 0).getJsonValue(); @@ -1225,12 +1227,12 @@ public void streamInitDiagnosticRecordedOnErrorDuringInit() throws Exception { // First result should be the error CompletableFuture result1Future = synchronizer.next(); FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); // Second result should be the successful changeset CompletableFuture result2Future = synchronizer.next(); FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); long timeAfterOpen = System.currentTimeMillis(); LDValue event = diagnosticStore.createEventAndReset(0, 0).getJsonValue(); @@ -1293,18 +1295,18 @@ public void streamRestartNotRecordedAsFailed() throws Exception { // First changeset CompletableFuture result1Future = synchronizer.next(); FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result1.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result1.getResultType()); // Goodbye CompletableFuture result2Future = synchronizer.next(); FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result2.getResultType()); - assertEquals(FDv2SourceResult.State.GOODBYE, result2.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result2.getResultType()); + assertEquals(SourceSignal.GOODBYE, result2.getStatus().getState()); // Second changeset after reconnect CompletableFuture result3Future = synchronizer.next(); FDv2SourceResult result3 = result3Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result3.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result3.getResultType()); LDValue event = diagnosticStore.createEventAndReset(0, 0).getJsonValue(); LDValue streamInits = event.get("streamInits"); @@ -1347,7 +1349,7 @@ public void nullDiagnosticStoreDoesNotCauseError() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); assertNotNull(result); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result.getResultType()); assertNotNull(result.getChangeSet()); synchronizer.close(); @@ -1403,27 +1405,27 @@ public void multipleRestartsRecordMultipleDiagnostics() throws Exception { // First changeset CompletableFuture result1Future = synchronizer.next(); FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result1.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result1.getResultType()); // First goodbye CompletableFuture result2Future = synchronizer.next(); FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result2.getResultType()); + assertEquals(SourceResultType.STATUS, result2.getResultType()); // Second changeset CompletableFuture result3Future = synchronizer.next(); FDv2SourceResult result3 = result3Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result3.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result3.getResultType()); // Second goodbye CompletableFuture result4Future = synchronizer.next(); FDv2SourceResult result4 = result4Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result4.getResultType()); + assertEquals(SourceResultType.STATUS, result4.getResultType()); // Third changeset CompletableFuture result5Future = synchronizer.next(); FDv2SourceResult result5 = result5Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result5.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result5.getResultType()); LDValue event = diagnosticStore.createEventAndReset(0, 0).getJsonValue(); LDValue streamInits = event.get("streamInits"); @@ -1476,13 +1478,13 @@ public void streamRestartAfterInvalidDataRecordsMultipleDiagnostics() throws Exc // First result should be interrupted due to invalid data CompletableFuture result1Future = synchronizer.next(); FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); - assertEquals(FDv2SourceResult.State.INTERRUPTED, result1.getStatus().getState()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); + assertEquals(SourceSignal.INTERRUPTED, result1.getStatus().getState()); // Second result should be the valid changeset CompletableFuture result2Future = synchronizer.next(); FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result2.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result2.getResultType()); LDValue event = diagnosticStore.createEventAndReset(0, 0).getJsonValue(); LDValue streamInits = event.get("streamInits"); @@ -1531,17 +1533,17 @@ public void multipleErrorsRecordMultipleDiagnostics() throws Exception { // First error CompletableFuture result1Future = synchronizer.next(); FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); + assertEquals(SourceResultType.STATUS, result1.getResultType()); // Second error CompletableFuture result2Future = synchronizer.next(); FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result2.getResultType()); + assertEquals(SourceResultType.STATUS, result2.getResultType()); // Successful changeset CompletableFuture result3Future = synchronizer.next(); FDv2SourceResult result3 = result3Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result3.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result3.getResultType()); long timeAfterOpen = System.currentTimeMillis(); LDValue event = diagnosticStore.createEventAndReset(0, 0).getJsonValue(); @@ -1609,22 +1611,22 @@ public void errorAfterSuccessfulChangesetRecordsNewDiagnostic() throws Exception // First successful changeset CompletableFuture result1Future = synchronizer.next(); FDv2SourceResult result1 = result1Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result1.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result1.getResultType()); // Goodbye CompletableFuture result2Future = synchronizer.next(); FDv2SourceResult result2 = result2Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result2.getResultType()); + assertEquals(SourceResultType.STATUS, result2.getResultType()); // Error CompletableFuture result3Future = synchronizer.next(); FDv2SourceResult result3 = result3Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.STATUS, result3.getResultType()); + assertEquals(SourceResultType.STATUS, result3.getResultType()); // Second successful changeset CompletableFuture result4Future = synchronizer.next(); FDv2SourceResult result4 = result4Future.get(5, TimeUnit.SECONDS); - assertEquals(FDv2SourceResult.ResultType.CHANGE_SET, result4.getResultType()); + assertEquals(SourceResultType.CHANGE_SET, result4.getResultType()); LDValue event = diagnosticStore.createEventAndReset(0, 0).getJsonValue(); LDValue streamInits = event.get("streamInits"); diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/TestComponents.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/TestComponents.java index 064580ae..77b4d699 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/TestComponents.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/TestComponents.java @@ -25,7 +25,7 @@ import com.launchdarkly.sdk.server.subsystems.DataSource; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSink; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSinkV2; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSet; import com.launchdarkly.sdk.server.subsystems.DataStore; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; @@ -35,6 +35,7 @@ import com.launchdarkly.sdk.server.subsystems.HttpConfiguration; import java.io.IOException; +import java.util.Map; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -206,7 +207,7 @@ public static class UpsertParams { statusBroadcaster; public final BlockingQueue> receivedInits = new LinkedBlockingQueue<>(); public final BlockingQueue receivedUpserts = new LinkedBlockingQueue<>(); - public final BlockingQueue> receivedApplies = new LinkedBlockingQueue<>(); + public final BlockingQueue>>>> receivedApplies = new LinkedBlockingQueue<>(); public MockDataSourceUpdates(DataStore store, DataStoreStatusProvider dataStoreStatusProvider) { this.dataStoreStatusProvider = dataStoreStatusProvider; @@ -248,7 +249,7 @@ public void updateStatus(State newState, ErrorInfo newError) { } @Override - public boolean apply(ChangeSet changeSet) { + public boolean apply(ChangeSet>>> changeSet) { boolean result = wrappedInstance.apply(changeSet); receivedApplies.add(changeSet); return result; diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/WriteThroughStoreTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/WriteThroughStoreTest.java index ea8827ff..767320f5 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/WriteThroughStoreTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/WriteThroughStoreTest.java @@ -2,11 +2,11 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider.CacheStats; import com.launchdarkly.sdk.server.subsystems.DataStore; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; @@ -53,7 +53,7 @@ private FullDataSet createTestDataSet() { .build(); } - private ChangeSet createFullChangeSet() { + private ChangeSet>>> createFullChangeSet() { Map> changeSetData = ImmutableMap.of( TEST_ITEMS, new KeyedItems<>(ImmutableList.of( @@ -303,7 +303,7 @@ public void applyWithFullChangeSetAppliesToBothStores() throws Exception { store = new WriteThroughStore(memoryStore, persistentStore, DataStoreMode.READ_WRITE); - ChangeSet changeSet = createFullChangeSet(); + ChangeSet>>> changeSet = createFullChangeSet(); store.apply(changeSet); assertTrue(memoryStore.isInitialized()); @@ -327,7 +327,7 @@ public void applyWithPartialChangeSetAppliesToBothStores() throws Exception { )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -351,7 +351,7 @@ public void applyWithLegacyPersistentStoreFullChangeSetCallsInit() throws Except store = new WriteThroughStore(memoryStore, persistentStore, DataStoreMode.READ_WRITE); - ChangeSet changeSet = createFullChangeSet(); + ChangeSet>>> changeSet = createFullChangeSet(); store.apply(changeSet); assertTrue(persistentStore.wasInitCalled); @@ -374,7 +374,7 @@ public void applyWithLegacyPersistentStorePartialChangeSetCallsUpsert() throws E )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -405,7 +405,7 @@ public void applyWithShouldPersistFalseDoesNotCallPersistentStore() throws Excep )) ); // Create change set with shouldPersist=false (e.g., from file data source) - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -434,7 +434,7 @@ public void applyWithFullChangeSetShouldPersistFalseDoesNotCallPersistentStore() store = new WriteThroughStore(memoryStore, persistentStore, DataStoreMode.READ_WRITE); // Create full change set with shouldPersist=false - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(1, "state1"), createFullChangeSet().getData(), @@ -461,7 +461,7 @@ public void applySwitchesActiveReadStoreToMemory() throws Exception { persistentStore.setData(TEST_ITEMS, "key1", new ItemDescriptor(5, new TestItem("key1", "old", 5))); - ChangeSet changeSet = createFullChangeSet(); + ChangeSet>>> changeSet = createFullChangeSet(); store.apply(changeSet); ItemDescriptor result = store.get(TEST_ITEMS, "key1"); @@ -542,7 +542,7 @@ public void selectorReturnsMemoryStoreSelector() throws Exception { store = new WriteThroughStore(memoryStore, persistentStore, DataStoreMode.READ_WRITE); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Full, Selector.make(42, "test-state"), ImmutableList.>>of(), @@ -623,7 +623,7 @@ public void applyWithLegacyStorePartialChangeSetThrowsWhenUpsertFails() throws E )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -662,7 +662,7 @@ public void applyWithLegacyStorePartialChangeSetThrowsWhenOneOfMultipleUpsertsFa )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -686,7 +686,7 @@ public void applyWithLegacyStoreFullChangeSetPropagatesInitException() throws Ex store = new WriteThroughStore(memoryStore, persistentStore, DataStoreMode.READ_WRITE); - ChangeSet changeSet = createFullChangeSet(); + ChangeSet>>> changeSet = createFullChangeSet(); try { store.apply(changeSet); @@ -704,7 +704,7 @@ public void applyWithTransactionalStorePropagatesApplyException() throws Excepti store = new WriteThroughStore(memoryStore, persistentStore, DataStoreMode.READ_WRITE); - ChangeSet changeSet = createFullChangeSet(); + ChangeSet>>> changeSet = createFullChangeSet(); try { store.apply(changeSet); @@ -732,7 +732,7 @@ public void applyWithLegacyStorePartialChangeSetMemoryStoreStillUpdatedBeforeExc )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -762,7 +762,7 @@ public void applyWithLegacyStoreNoneChangeSetDoesNotThrow() throws Exception { store.init(createTestDataSet()); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.None, Selector.make(2, "state2"), ImmutableList.>>of(), @@ -799,7 +799,7 @@ public void applySwitchesToMemoryStoreEvenWhenPersistentStoreApplyFails() throws )) ); - ChangeSet changeSet = new ChangeSet<>( + ChangeSet>>> changeSet = new ChangeSet<>( ChangeSetType.Partial, Selector.make(2, "state2"), changeSetData.entrySet(), @@ -843,7 +843,7 @@ public void applySwitchesToMemoryStoreEvenWhenTransactionalStoreApplyFails() thr assertNotNull(resultBefore); assertEquals(5, resultBefore.getVersion()); - ChangeSet changeSet = createFullChangeSet(); + ChangeSet>>> changeSet = createFullChangeSet(); // Apply should throw due to persistent store failure try { @@ -993,7 +993,7 @@ public void resetCallTracking() { } @Override - public void apply(ChangeSet changeSet) { + public void apply(ChangeSet>>> changeSet) { wasApplyCalled = true; if (throwOnApply) { throw new RuntimeException("Apply failed"); diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileInitializerTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileInitializerTest.java index 5e3559d9..95d9d923 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileInitializerTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileInitializerTest.java @@ -1,9 +1,11 @@ package com.launchdarkly.sdk.server.integrations; import com.launchdarkly.logging.LDLogger; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.Initializer; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import org.junit.Test; @@ -30,7 +32,7 @@ public void initializerReturnsChangeSetOnSuccessfulLoad() throws Exception { CompletableFuture resultFuture = initializer.run(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet(), notNullValue()); assertThat(result.getChangeSet().getType(), equalTo(ChangeSetType.Full)); assertNotNull(result.getChangeSet().getData()); @@ -46,8 +48,8 @@ public void initializerReturnsTerminalErrorOnMissingFile() throws Exception { CompletableFuture resultFuture = initializer.run(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.STATUS)); - assertThat(result.getStatus().getState(), equalTo(FDv2SourceResult.State.TERMINAL_ERROR)); + assertThat(result.getResultType(), equalTo(SourceResultType.STATUS)); + assertThat(result.getStatus().getState(), equalTo(SourceSignal.TERMINAL_ERROR)); assertNotNull(result.getStatus().getErrorInfo()); } } @@ -64,8 +66,8 @@ public void initializerReturnsShutdownWhenClosedBeforeRun() throws Exception { CompletableFuture resultFuture = initializer.run(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.STATUS)); - assertThat(result.getStatus().getState(), equalTo(FDv2SourceResult.State.SHUTDOWN)); + assertThat(result.getResultType(), equalTo(SourceResultType.STATUS)); + assertThat(result.getStatus().getState(), equalTo(SourceSignal.SHUTDOWN)); } @Test @@ -77,7 +79,7 @@ public void initializerCanLoadFromClasspathResource() throws Exception { CompletableFuture resultFuture = initializer.run(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet(), notNullValue()); } } @@ -96,7 +98,7 @@ public void initializerRespectsIgnoreDuplicateKeysHandling() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); // Should succeed when ignoring duplicates - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); } } @@ -109,7 +111,7 @@ public void initializerDefaultsToNotPersisting() throws Exception { CompletableFuture resultFuture = initializer.run(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet().shouldPersist(), equalTo(false)); } } @@ -124,7 +126,7 @@ public void initializerCanBeConfiguredToPersist() throws Exception { CompletableFuture resultFuture = initializer.run(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet().shouldPersist(), equalTo(true)); } } @@ -139,7 +141,7 @@ public void initializerCanBeConfiguredToNotPersist() throws Exception { CompletableFuture resultFuture = initializer.run(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet().shouldPersist(), equalTo(false)); } } @@ -157,8 +159,8 @@ public void initializerFailsOnDuplicateKeysByDefault() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); // Should fail with terminal error when duplicate keys are not allowed - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.STATUS)); - assertThat(result.getStatus().getState(), equalTo(FDv2SourceResult.State.TERMINAL_ERROR)); + assertThat(result.getResultType(), equalTo(SourceResultType.STATUS)); + assertThat(result.getStatus().getState(), equalTo(SourceSignal.TERMINAL_ERROR)); } } } diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileSynchronizerTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileSynchronizerTest.java index af600cf2..a39dc103 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileSynchronizerTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/FileSynchronizerTest.java @@ -1,9 +1,11 @@ package com.launchdarkly.sdk.server.integrations; import com.launchdarkly.logging.LDLogger; +import com.launchdarkly.sdk.fdv2.SourceResultType; +import com.launchdarkly.sdk.fdv2.SourceSignal; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.Synchronizer; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.testhelpers.TempDir; import com.launchdarkly.testhelpers.TempFile; @@ -33,7 +35,7 @@ public void synchronizerReturnsChangeSetOnSuccessfulLoad() throws Exception { CompletableFuture resultFuture = synchronizer.next(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet(), notNullValue()); assertThat(result.getChangeSet().getType(), equalTo(ChangeSetType.Full)); assertNotNull(result.getChangeSet().getData()); @@ -50,8 +52,8 @@ public void synchronizerReturnsInterruptedOnMissingFile() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); // Synchronizers return INTERRUPTED for recoverable errors, not TERMINAL_ERROR - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.STATUS)); - assertThat(result.getStatus().getState(), equalTo(FDv2SourceResult.State.INTERRUPTED)); + assertThat(result.getResultType(), equalTo(SourceResultType.STATUS)); + assertThat(result.getStatus().getState(), equalTo(SourceSignal.INTERRUPTED)); assertNotNull(result.getStatus().getErrorInfo()); } } @@ -65,7 +67,7 @@ public void synchronizerReturnsShutdownWhenClosed() throws Exception { // Get initial result CompletableFuture initialResult = synchronizer.next(); FDv2SourceResult result = initialResult.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); // Start waiting for next result CompletableFuture nextResult = synchronizer.next(); @@ -75,8 +77,8 @@ public void synchronizerReturnsShutdownWhenClosed() throws Exception { // Should return shutdown result = nextResult.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.STATUS)); - assertThat(result.getStatus().getState(), equalTo(FDv2SourceResult.State.SHUTDOWN)); + assertThat(result.getResultType(), equalTo(SourceResultType.STATUS)); + assertThat(result.getStatus().getState(), equalTo(SourceSignal.SHUTDOWN)); } @Test @@ -88,7 +90,7 @@ public void synchronizerCanLoadFromClasspathResource() throws Exception { CompletableFuture resultFuture = synchronizer.next(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet(), notNullValue()); } } @@ -107,7 +109,7 @@ public void synchronizerRespectsIgnoreDuplicateKeysHandling() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); // Should succeed when ignoring duplicates - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); } } @@ -124,8 +126,8 @@ public void synchronizerFailsOnDuplicateKeysByDefault() throws Exception { FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); // Should fail with interrupted error when duplicate keys are not allowed - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.STATUS)); - assertThat(result.getStatus().getState(), equalTo(FDv2SourceResult.State.INTERRUPTED)); + assertThat(result.getResultType(), equalTo(SourceResultType.STATUS)); + assertThat(result.getStatus().getState(), equalTo(SourceSignal.INTERRUPTED)); } } @@ -142,7 +144,7 @@ public void synchronizerAutoUpdateEmitsNewResultOnFileChange() throws Exception // Get initial result CompletableFuture resultFuture = synchronizer.next(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); // Start waiting for next result CompletableFuture nextResultFuture = synchronizer.next(); @@ -154,7 +156,7 @@ public void synchronizerAutoUpdateEmitsNewResultOnFileChange() throws Exception // Should get a new result with the updated data // Note: File watching on MacOS can take up to 10 seconds result = nextResultFuture.get(15, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); } } } @@ -169,7 +171,7 @@ public void synchronizerDefaultsToNotPersisting() throws Exception { CompletableFuture resultFuture = synchronizer.next(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet().shouldPersist(), equalTo(false)); } } @@ -184,7 +186,7 @@ public void synchronizerCanBeConfiguredToPersist() throws Exception { CompletableFuture resultFuture = synchronizer.next(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet().shouldPersist(), equalTo(true)); } } @@ -199,7 +201,7 @@ public void synchronizerCanBeConfiguredToNotPersist() throws Exception { CompletableFuture resultFuture = synchronizer.next(); FDv2SourceResult result = resultFuture.get(5, TimeUnit.SECONDS); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(result.getChangeSet().shouldPersist(), equalTo(false)); } } diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataSourceBuildInputs.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataSourceBuildInputs.java index ad80c633..20c9b6e3 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataSourceBuildInputs.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataSourceBuildInputs.java @@ -1,7 +1,7 @@ package com.launchdarkly.sdk.server.integrations; import com.launchdarkly.logging.LDLogger; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import com.launchdarkly.sdk.server.Components; import com.launchdarkly.sdk.server.interfaces.ServiceEndpoints; import com.launchdarkly.sdk.server.subsystems.DataSourceBuildInputs; diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataTest.java index 58fbc96b..5a81d322 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataTest.java @@ -12,10 +12,11 @@ import com.launchdarkly.sdk.server.subsystems.DataSource; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSink; import com.launchdarkly.sdk.server.subsystems.DataSourceUpdateSinkV2; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.FullDataSet; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; +import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; import org.junit.Test; @@ -471,7 +472,7 @@ private static class UpsertParams { private static class CapturingDataSourceUpdates implements DataSourceUpdateSink, DataSourceUpdateSinkV2 { BlockingQueue> inits = new LinkedBlockingQueue<>(); BlockingQueue upserts = new LinkedBlockingQueue<>(); - BlockingQueue> applies = new LinkedBlockingQueue<>(); + BlockingQueue>>>> applies = new LinkedBlockingQueue<>(); boolean valid; @Override @@ -497,7 +498,7 @@ public void updateStatus(State newState, ErrorInfo newError) { } @Override - public boolean apply(ChangeSet changeSet) { + public boolean apply(ChangeSet>>> changeSet) { applies.add(changeSet); return true; } diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataV2Test.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataV2Test.java index cd1dd13c..0a20949b 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataV2Test.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataV2Test.java @@ -6,6 +6,7 @@ import com.launchdarkly.sdk.server.DataModel; import com.launchdarkly.sdk.server.LDConfig; import com.launchdarkly.sdk.server.ModelBuilders; +import com.launchdarkly.sdk.fdv2.SourceResultType; import com.launchdarkly.sdk.server.datasources.FDv2SourceResult; import com.launchdarkly.sdk.server.datasources.SelectorSource; import com.launchdarkly.sdk.server.datasources.Synchronizer; @@ -14,13 +15,13 @@ import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider; import com.launchdarkly.sdk.server.subsystems.ClientContext; import com.launchdarkly.sdk.server.subsystems.DataSourceBuildInputs; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSet; -import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ChangeSetType; +import com.launchdarkly.sdk.fdv2.ChangeSet; +import com.launchdarkly.sdk.fdv2.ChangeSetType; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.DataKind; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.ItemDescriptor; import com.launchdarkly.sdk.server.subsystems.DataStoreTypes.KeyedItems; -import com.launchdarkly.sdk.internal.fdv2.sources.Selector; +import com.launchdarkly.sdk.fdv2.Selector; import org.junit.Test; import java.util.Map; @@ -109,8 +110,8 @@ public void initializesWithEmptyData() throws Exception { FDv2SourceResult result = consumer.next(); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); - ChangeSet changeSet = result.getChangeSet(); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); + ChangeSet>>> changeSet = result.getChangeSet(); assertThat(changeSet, notNullValue()); assertThat(changeSet.getType(), equalTo(ChangeSetType.Full)); assertThat(changeSet.getData(), iterableWithSize(1)); @@ -131,8 +132,8 @@ public void initializesWithFlags() throws Exception { FDv2SourceResult result = consumer.next(); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); - ChangeSet changeSet = result.getChangeSet(); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); + ChangeSet>>> changeSet = result.getChangeSet(); assertThat(changeSet.getType(), equalTo(ChangeSetType.Full)); assertThat(changeSet.getData(), iterableWithSize(1)); assertThat(get(changeSet.getData(), 0).getKey(), equalTo(DataModel.FEATURES)); @@ -164,14 +165,14 @@ public void addsFlag() throws Exception { ResultConsumer consumer = new ResultConsumer(sync); FDv2SourceResult initResult = consumer.next(); - assertThat(initResult.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(initResult.getResultType(), equalTo(SourceResultType.CHANGE_SET)); assertThat(initResult.getChangeSet().getType(), equalTo(ChangeSetType.Full)); td.update(td.flag("flag1").on(true)); FDv2SourceResult updateResult = consumer.next(); - assertThat(updateResult.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); - ChangeSet changeSet = updateResult.getChangeSet(); + assertThat(updateResult.getResultType(), equalTo(SourceResultType.CHANGE_SET)); + ChangeSet>>> changeSet = updateResult.getChangeSet(); assertThat(changeSet.getType(), equalTo(ChangeSetType.Partial)); assertThat(changeSet.getData(), iterableWithSize(1)); KeyedItems keyedItems = get(changeSet.getData(), 0).getValue(); @@ -200,12 +201,12 @@ public void updatesFlag() throws Exception { ResultConsumer consumer = new ResultConsumer(sync); FDv2SourceResult initResult = consumer.next(); - assertThat(initResult.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); + assertThat(initResult.getResultType(), equalTo(SourceResultType.CHANGE_SET)); td.update(td.flag("flag1").on(true)); FDv2SourceResult updateResult = consumer.next(); - ChangeSet changeSet = updateResult.getChangeSet(); + ChangeSet>>> changeSet = updateResult.getChangeSet(); Map items = ImmutableMap.copyOf(get(changeSet.getData(), 0).getValue().getItems()); ItemDescriptor flag1 = items.get("flag1"); assertThat(flag1.getVersion(), equalTo(2)); @@ -306,8 +307,8 @@ private void verifyFlag( td.update(configureFlag.apply(td.flag("flagkey"))); FDv2SourceResult result = consumer.next(); - assertThat(result.getResultType(), equalTo(FDv2SourceResult.ResultType.CHANGE_SET)); - ChangeSet changeSet = result.getChangeSet(); + assertThat(result.getResultType(), equalTo(SourceResultType.CHANGE_SET)); + ChangeSet>>> changeSet = result.getChangeSet(); Map items = ImmutableMap.copyOf(get(changeSet.getData(), 0).getValue().getItems()); ItemDescriptor flag = items.get("flagkey"); assertThat(flag.getVersion(), equalTo(1)); @@ -329,7 +330,7 @@ private static class CapturingDataSourceUpdates implements com.launchdarkly.sdk. BlockingQueue> inits = new LinkedBlockingQueue<>(); BlockingQueue upserts = new LinkedBlockingQueue<>(); - BlockingQueue> applies = new LinkedBlockingQueue<>(); + BlockingQueue>>>> applies = new LinkedBlockingQueue<>(); boolean valid; @Override @@ -355,7 +356,7 @@ public void updateStatus(State newState, ErrorInfo newError) { } @Override - public boolean apply(ChangeSet changeSet) { + public boolean apply(ChangeSet>>> changeSet) { applies.add(changeSet); return true; } From aeda35abf2bdc7eb0ef63bcddc6437269bc6d0f1 Mon Sep 17 00:00:00 2001 From: Todd Anderson Date: Fri, 27 Feb 2026 11:41:31 -0500 Subject: [PATCH 4/4] fixing class shading and review comment --- lib/sdk/server/build.gradle | 2 +- .../com/launchdarkly/sdk/server/DataModelDependencies.java | 3 +++ .../src/main/java/com/launchdarkly/sdk/server/PollingBase.java | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/sdk/server/build.gradle b/lib/sdk/server/build.gradle index c683f281..7040f13a 100644 --- a/lib/sdk/server/build.gradle +++ b/lib/sdk/server/build.gradle @@ -291,7 +291,7 @@ javadoc { // enclosing packages like "com" that don't have any classes in them. def getAllSdkPackages() { // base package classes come from launchdarkly-java-sdk-common - def names = [ "com.launchdarkly.sdk", "com.launchdarkly.sdk.json", "com.launchdarkly.logging" ] + def names = [ "com.launchdarkly.sdk", "com.launchdarkly.sdk.json", "com.launchdarkly.sdk.fdv2", "com.launchdarkly.logging" ] project.convention.getPlugin(JavaPluginConvention).sourceSets.main.output.each { baseDir -> if (baseDir.getPath().contains("classes" + File.separator + "java" + File.separator + "main")) { baseDir.eachFileRecurse { f -> diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataModelDependencies.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataModelDependencies.java index 2fa3f3dc..57a4a16c 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataModelDependencies.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/DataModelDependencies.java @@ -142,6 +142,9 @@ public static FullDataSet sortAllCollections(FullDataSet>>> sortChangeset(ChangeSet>>> inSet) { + if (inSet.getData() == null) { + return inSet; + } ImmutableSortedMap.Builder> builder = ImmutableSortedMap.orderedBy(dataKindPriorityOrder); for (Map.Entry> entry: inSet.getData()) { diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java index 0a570971..c21bd5ba 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java @@ -15,6 +15,7 @@ import com.launchdarkly.sdk.json.SerializationException; import java.io.IOException; +import java.util.Collections; import java.util.Map; import java.util.Date; import java.util.concurrent.CompletableFuture; @@ -91,7 +92,7 @@ protected CompletableFuture poll(Selector selector, boolean on return FDv2SourceResult.changeSet( new ChangeSet<>(ChangeSetType.None, Selector.EMPTY, - null, + Collections.emptyList(), null, // Header derived values will have been handled on initial response. true // Polling data from LaunchDarkly should be persisted ),