diff --git a/DotnetCore.sln b/DotnetCore.sln index 4a8def12..e70da71d 100644 --- a/DotnetCore.sln +++ b/DotnetCore.sln @@ -72,9 +72,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "telemetry", "telemetry", "{ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaunchDarkly.ServerSdk.Telemetry", "pkgs\telemetry\src\LaunchDarkly.ServerSdk.Telemetry.csproj", "{DE321396-6459-4C02-AF61-1A2677A7CB65}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sandbox", "sandbox", "{822D49A6-1DF2-49BB-A3C0-15821ED718D6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnet-server-sandbox", "sandbox\dotnet-server-sandbox\dotnet-server-sandbox.csproj", "{A10B580F-D937-4EA8-8CF8-4F130FBF6C16}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "repo-docs", "repo-docs", "{1A854A11-54BE-4978-B4FF-0A2AE2488C2A}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + SECURITY.md = SECURITY.md + CONTRIBUTING.md = CONTRIBUTING.md + LICENSE = LICENSE + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + DebugLocalReferences|Any CPU = DebugLocalReferences|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution @@ -107,87 +120,134 @@ Global {EF541D97-2C23-4FB8-BD87-ADFDF0FF83F3} = {0007CF48-139C-43C6-8A3A-2A2D1474F197} {561F6F3D-09C5-470A-83AC-F0E97BAD609B} = {EF541D97-2C23-4FB8-BD87-ADFDF0FF83F3} {DE321396-6459-4C02-AF61-1A2677A7CB65} = {FF3153CA-F727-4666-BA1E-5459BE34FBAB} + {A10B580F-D937-4EA8-8CF8-4F130FBF6C16} = {822D49A6-1DF2-49BB-A3C0-15821ED718D6} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Release|Any CPU.ActiveCfg = Release|Any CPU {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Release|Any CPU.Build.0 = Release|Any CPU + {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Release|Any CPU.ActiveCfg = Release|Any CPU {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Release|Any CPU.Build.0 = Release|Any CPU + {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {D1DF71E8-6037-4E35-813A-07F5A27153C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D1DF71E8-6037-4E35-813A-07F5A27153C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {D1DF71E8-6037-4E35-813A-07F5A27153C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {D1DF71E8-6037-4E35-813A-07F5A27153C2}.Release|Any CPU.Build.0 = Release|Any CPU + {D1DF71E8-6037-4E35-813A-07F5A27153C2}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {D1DF71E8-6037-4E35-813A-07F5A27153C2}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {A2733CF1-672F-41A8-8DF8-7340BF953457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A2733CF1-672F-41A8-8DF8-7340BF953457}.Debug|Any CPU.Build.0 = Debug|Any CPU {A2733CF1-672F-41A8-8DF8-7340BF953457}.Release|Any CPU.ActiveCfg = Release|Any CPU {A2733CF1-672F-41A8-8DF8-7340BF953457}.Release|Any CPU.Build.0 = Release|Any CPU + {A2733CF1-672F-41A8-8DF8-7340BF953457}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {A2733CF1-672F-41A8-8DF8-7340BF953457}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Release|Any CPU.ActiveCfg = Release|Any CPU {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Release|Any CPU.Build.0 = Release|Any CPU {14026C03-B639-459C-8E23-B99E2FB68C10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {14026C03-B639-459C-8E23-B99E2FB68C10}.Debug|Any CPU.Build.0 = Debug|Any CPU {14026C03-B639-459C-8E23-B99E2FB68C10}.Release|Any CPU.ActiveCfg = Release|Any CPU {14026C03-B639-459C-8E23-B99E2FB68C10}.Release|Any CPU.Build.0 = Release|Any CPU + {14026C03-B639-459C-8E23-B99E2FB68C10}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {14026C03-B639-459C-8E23-B99E2FB68C10}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Debug|Any CPU.Build.0 = Debug|Any CPU {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Release|Any CPU.ActiveCfg = Release|Any CPU {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Release|Any CPU.Build.0 = Release|Any CPU + {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {1D41FF94-B814-4FF3-A565-518DC9759140}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1D41FF94-B814-4FF3-A565-518DC9759140}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D41FF94-B814-4FF3-A565-518DC9759140}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {1D41FF94-B814-4FF3-A565-518DC9759140}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {1D41FF94-B814-4FF3-A565-518DC9759140}.Release|Any CPU.ActiveCfg = Release|Any CPU {1D41FF94-B814-4FF3-A565-518DC9759140}.Release|Any CPU.Build.0 = Release|Any CPU {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Release|Any CPU.ActiveCfg = Release|Any CPU {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Release|Any CPU.Build.0 = Release|Any CPU + {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Debug|Any CPU.Build.0 = Debug|Any CPU {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Release|Any CPU.ActiveCfg = Release|Any CPU {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Release|Any CPU.Build.0 = Release|Any CPU + {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {06C06727-7A8F-417E-9164-5C70AD96A94F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {06C06727-7A8F-417E-9164-5C70AD96A94F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06C06727-7A8F-417E-9164-5C70AD96A94F}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {06C06727-7A8F-417E-9164-5C70AD96A94F}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {06C06727-7A8F-417E-9164-5C70AD96A94F}.Release|Any CPU.ActiveCfg = Release|Any CPU {06C06727-7A8F-417E-9164-5C70AD96A94F}.Release|Any CPU.Build.0 = Release|Any CPU {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Debug|Any CPU.Build.0 = Debug|Any CPU {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Release|Any CPU.ActiveCfg = Release|Any CPU {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Release|Any CPU.Build.0 = Release|Any CPU + {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Release|Any CPU.Build.0 = Release|Any CPU {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Debug|Any CPU.Build.0 = Debug|Any CPU {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Release|Any CPU.ActiveCfg = Release|Any CPU {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Release|Any CPU.Build.0 = Release|Any CPU + {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Release|Any CPU.ActiveCfg = Release|Any CPU {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Release|Any CPU.Build.0 = Release|Any CPU {8C027074-CF8D-437F-9CE8-0F8180E496AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8C027074-CF8D-437F-9CE8-0F8180E496AA}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C027074-CF8D-437F-9CE8-0F8180E496AA}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C027074-CF8D-437F-9CE8-0F8180E496AA}.Release|Any CPU.Build.0 = Release|Any CPU + {8C027074-CF8D-437F-9CE8-0F8180E496AA}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {8C027074-CF8D-437F-9CE8-0F8180E496AA}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {ED864025-2BDC-4AED-8A53-FAB852772132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ED864025-2BDC-4AED-8A53-FAB852772132}.Debug|Any CPU.Build.0 = Debug|Any CPU {ED864025-2BDC-4AED-8A53-FAB852772132}.Release|Any CPU.ActiveCfg = Release|Any CPU {ED864025-2BDC-4AED-8A53-FAB852772132}.Release|Any CPU.Build.0 = Release|Any CPU + {ED864025-2BDC-4AED-8A53-FAB852772132}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {ED864025-2BDC-4AED-8A53-FAB852772132}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Release|Any CPU.Build.0 = Release|Any CPU + {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU + {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Release|Any CPU.ActiveCfg = Release|Any CPU {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Release|Any CPU.Build.0 = Release|Any CPU {DE321396-6459-4C02-AF61-1A2677A7CB65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DE321396-6459-4C02-AF61-1A2677A7CB65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE321396-6459-4C02-AF61-1A2677A7CB65}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {DE321396-6459-4C02-AF61-1A2677A7CB65}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU {DE321396-6459-4C02-AF61-1A2677A7CB65}.Release|Any CPU.ActiveCfg = Release|Any CPU {DE321396-6459-4C02-AF61-1A2677A7CB65}.Release|Any CPU.Build.0 = Release|Any CPU + {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Release|Any CPU.Build.0 = Release|Any CPU + {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU + {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU EndGlobalSection EndGlobal diff --git a/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj b/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj index b0180227..0ebac19b 100644 --- a/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj +++ b/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj @@ -20,17 +20,53 @@ true snupkg LaunchDarkly.Sdk.Server.Integrations + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE + + + + + + + + + + + + CHANGELOG.md + + + CONTRIBUTING.md + + + docfx.json + + + index.md + + + README.md + + + SECURITY.md + + + bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.ServerSdk.Consul.xml diff --git a/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj b/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj index 3a104d5c..501eb0d5 100644 --- a/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj +++ b/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj @@ -20,13 +20,48 @@ true snupkg LaunchDarkly.Sdk.Server.Integrations + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE + + + + + + + + + + + CHANGELOG.md + + + CONTRIBUTING.md + + + docfx.json + + + index.md + + + README.md + + + SECURITY.md + + + bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.ServerSdk.DynamoDB.xml diff --git a/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj b/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj index 8bcb70ef..3e1278f5 100644 --- a/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj +++ b/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj @@ -20,13 +20,45 @@ true snupkg LaunchDarkly.Sdk.Server.Integrations + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE - + + + + + + + + + + + + CHANGELOG.md + + + CONTRIBUTING.md + + + docfx.json + + + README.md + + + SECURITY.md + + + bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.ServerSdk.Redis.xml diff --git a/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj b/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj index 37085312..37533a3d 100644 --- a/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj +++ b/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj @@ -37,6 +37,12 @@ 1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712 + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE @@ -118,6 +124,23 @@ + + + CHANGELOG.md + + + CONTRIBUTING.md + + + index.md + + + README.md + + + toc.yml + + ../../../../LaunchDarkly.ClientSdk.snk true diff --git a/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj b/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj index 695c713f..c218056c 100644 --- a/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj +++ b/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj @@ -35,13 +35,51 @@ 1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712 + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE - + + + + + + + + + + + + CHANGELOG.md + + + CONTRIBUTING.md + + + docfx.json + + + docs-src\namespaces\LaunchDarkly.Sdk.Server.Ai.md + + + docs-src\README.md + + + index.md + + + README.md + + + ../../../../LaunchDarkly.snk true diff --git a/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj b/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj index 67102b1f..ac18b50a 100644 --- a/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj +++ b/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj @@ -35,6 +35,12 @@ 1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712 + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE @@ -51,6 +57,45 @@ + + + CHANGELOG.md + + + CONTRIBUTING.md + + + docfx.json + + + docs-src\namespaces\LaunchDarkly.Sdk.Json.md + + + docs-src\namespaces\LaunchDarkly.Sdk.md + + + docs-src\namespaces\LaunchDarkly.Sdk.Server.Integrations.md + + + docs-src\namespaces\LaunchDarkly.Sdk.Server.Interfaces.md + + + docs-src\namespaces\LaunchDarkly.Sdk.Server.md + + + docs-src\namespaces\LaunchDarkly.Sdk.Server.Subsystems.md + + + docs-src\README.md + + + index.md + + + README.md + + + ../../../../LaunchDarkly.snk true diff --git a/pkgs/sdk/server/src/Properties/AssemblyInfo.cs b/pkgs/sdk/server/src/Properties/AssemblyInfo.cs index d40c5c1d..a732335e 100644 --- a/pkgs/sdk/server/src/Properties/AssemblyInfo.cs +++ b/pkgs/sdk/server/src/Properties/AssemblyInfo.cs @@ -14,7 +14,7 @@ // Allow unit tests to see internal classes (note, the test assembly is not signed; // tests must be run against the Debug configuration of this assembly) [assembly: InternalsVisibleTo("LaunchDarkly.ServerSdk.Tests")] -[assembly: InternalsVisibleTo("dotnet-server-test-app")] +[assembly: InternalsVisibleTo("dotnet-server-sandbox")] // Allow contract tests to see internal classes [assembly: InternalsVisibleTo("ContractTestService")] diff --git a/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj b/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj index a74fd8e4..921daaf5 100644 --- a/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj +++ b/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj @@ -34,6 +34,12 @@ bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.CommonSdk.xml LaunchDarkly.Sdk + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE diff --git a/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj b/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj index dd78456f..5c14f270 100644 --- a/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj +++ b/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj @@ -10,11 +10,26 @@ Copyright 2020 Catamorphic, Co. Apache-2.0 LaunchDarkly.Sdk.Server.SharedTests + Debug;Release;DebugLocalReferences + AnyCPU + + + + DEBUG;TRACE - + + + + + + + + + + diff --git a/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj b/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj index d7f332eb..9818d80f 100644 --- a/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj +++ b/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj @@ -34,17 +34,41 @@ 1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712 + Debug;Release;DebugLocalReferences + AnyCPU - + + DEBUG;TRACE + + + + + + + + + + + + CHANGELOG.md + + + docfx.json + + + index.md + + + ../../../LaunchDarkly.snk true diff --git a/sandbox/dotnet-server-sandbox/Configuration/DataSystemConfigurationBuilder.cs b/sandbox/dotnet-server-sandbox/Configuration/DataSystemConfigurationBuilder.cs new file mode 100644 index 00000000..c9354353 --- /dev/null +++ b/sandbox/dotnet-server-sandbox/Configuration/DataSystemConfigurationBuilder.cs @@ -0,0 +1,108 @@ +using LaunchDarkly.Sdk.Server; +using LaunchDarkly.Sdk.Server.Integrations; + +namespace dotnet_server_test_app.Configuration; + +/// +/// Builds DataSystem configurations based on environment variables. +/// +internal static class DataSystemConfigurationBuilder +{ + /// + /// Builds a DataSystem configuration based on LAUNCHDARKLY_DATA_SYSTEM_MODE environment variable. + /// Returns null if using the default mode (which doesn't need explicit configuration). + /// + internal static DataSystemBuilder? Build() + { + var mode = EnvironmentVariables.GetString( + EnvironmentVariables.DataSystemMode, + EnvironmentVariables.DefaultDataSystemMode); + + return mode.ToLower() switch + { + "default" => BuildDefault(), + "streaming" => BuildStreaming(), + "polling" => BuildPolling(), + "daemon" => BuildDaemon(), + "persistent-store" => BuildPersistentStore(), + _ => throw new ArgumentException( + $"Invalid data system mode: got '{mode}', expected one of: default, streaming, polling, daemon, persistent-store") + }; + } + + /// + /// Builds the default DataSystem configuration (CDN + streaming with fallback). + /// + private static DataSystemBuilder BuildDefault() + { + return Components.DataSystem().Default(); + } + + /// + /// Builds a streaming-only DataSystem configuration. + /// + private static DataSystemBuilder BuildStreaming() + { + return Components.DataSystem().Streaming(); + } + + /// + /// Builds a polling-only DataSystem configuration. + /// + private static DataSystemBuilder BuildPolling() + { + return Components.DataSystem().Polling(); + } + + /// + /// Builds a daemon mode DataSystem configuration (read-only from persistent store). + /// Requires a persistent store to be configured. + /// + private static DataSystemBuilder BuildDaemon() + { + var persistentStore = PersistentStoreConfigurationBuilder.Build(); + + if (persistentStore == null) + { +#if DEBUG_LOCAL_REFERENCES + throw new InvalidOperationException( + $"{EnvironmentVariables.DataSystemMode} is set to 'daemon' but {EnvironmentVariables.PersistentStoreType} is not configured. " + + "Daemon mode requires a persistent store."); +#else + Console.WriteLine("ERROR: Daemon mode requires a persistent store, but persistent store support is not available in this build configuration."); + Console.WriteLine("Please rebuild with DebugLocalReferences configuration to use Redis or DynamoDB persistent stores."); + Console.WriteLine(" dotnet build -c DebugLocalReferences"); + throw new InvalidOperationException( + "Daemon mode requires persistent store support. Rebuild with DebugLocalReferences configuration."); +#endif + } + + return Components.DataSystem().Daemon(persistentStore); + } + + /// + /// Builds a persistent store DataSystem configuration (default mode + persistent store backup). + /// Requires a persistent store to be configured. + /// + private static DataSystemBuilder BuildPersistentStore() + { + var persistentStore = PersistentStoreConfigurationBuilder.Build(); + + if (persistentStore == null) + { +#if DEBUG_LOCAL_REFERENCES + throw new InvalidOperationException( + $"{EnvironmentVariables.DataSystemMode} is set to 'persistent-store' but {EnvironmentVariables.PersistentStoreType} is not configured. " + + "Persistent-store mode requires a persistent store."); +#else + Console.WriteLine("ERROR: Persistent-store mode requires a persistent store, but persistent store support is not available in this build configuration."); + Console.WriteLine("Please rebuild with DebugLocalReferences configuration to use Redis or DynamoDB persistent stores."); + Console.WriteLine(" dotnet build -c DebugLocalReferences"); + throw new InvalidOperationException( + "Persistent-store mode requires persistent store support. Rebuild with DebugLocalReferences configuration."); +#endif + } + + return Components.DataSystem().PersistentStore(persistentStore); + } +} diff --git a/sandbox/dotnet-server-sandbox/Configuration/EnvironmentVariables.cs b/sandbox/dotnet-server-sandbox/Configuration/EnvironmentVariables.cs new file mode 100644 index 00000000..ebd6bf43 --- /dev/null +++ b/sandbox/dotnet-server-sandbox/Configuration/EnvironmentVariables.cs @@ -0,0 +1,110 @@ +namespace dotnet_server_test_app.Configuration; + +/// +/// Centralized environment variable names, defaults, and parsing utilities for SDK configuration. +/// +public static class EnvironmentVariables +{ + // Environment variable names + public const string SdkKey = "LAUNCHDARKLY_SDK_KEY"; + public const string Offline = "LAUNCHDARKLY_OFFLINE"; + public const string DataSystemMode = "LAUNCHDARKLY_DATA_SYSTEM_MODE"; + public const string StartWaitTimeMs = "LAUNCHDARKLY_START_WAIT_TIME_MS"; + public const string PersistentStoreType = "LAUNCHDARKLY_PERSISTENT_STORE_TYPE"; + + // Redis configuration + public const string RedisHost = "LAUNCHDARKLY_REDIS_HOST"; + public const string RedisPort = "LAUNCHDARKLY_REDIS_PORT"; + public const string RedisPrefix = "LAUNCHDARKLY_REDIS_PREFIX"; + public const string RedisConnectTimeoutMs = "LAUNCHDARKLY_REDIS_CONNECT_TIMEOUT_MS"; + public const string RedisOperationTimeoutMs = "LAUNCHDARKLY_REDIS_OPERATION_TIMEOUT_MS"; + + // DynamoDB configuration + public const string DynamoDBTableName = "LAUNCHDARKLY_DYNAMODB_TABLE_NAME"; + public const string DynamoDBPrefix = "LAUNCHDARKLY_DYNAMODB_PREFIX"; + + // Default values + public const bool DefaultOffline = false; + public const string DefaultDataSystemMode = "default"; + public const int DefaultStartWaitTimeMs = 10000; + + public const string DefaultRedisHost = "localhost"; + public const int DefaultRedisPort = 6379; + public const string DefaultRedisPrefix = "launchdarkly"; + public const int DefaultRedisConnectTimeoutMs = 5000; + public const int DefaultRedisOperationTimeoutMs = 3000; + + public const string DefaultDynamoDBPrefix = ""; + + /// + /// Gets a string environment variable value or returns the default if not set. + /// + public static string GetString(string varName, string defaultValue) + { + var value = Environment.GetEnvironmentVariable(varName); + return string.IsNullOrEmpty(value) ? defaultValue : value; + } + + /// + /// Parses an integer environment variable value or returns the default if not set. + /// Throws FormatException if the value is invalid. + /// + public static int ParseInt(string varName, int defaultValue) + { + var value = Environment.GetEnvironmentVariable(varName); + if (string.IsNullOrEmpty(value)) + { + return defaultValue; + } + + if (int.TryParse(value, out var result)) + { + return result; + } + + throw new FormatException($"Invalid integer value for {varName}: got '{value}', expected a valid integer"); + } + + /// + /// Parses a boolean environment variable value or returns the default if not set. + /// Accepts "true"/"false" (case insensitive). + /// Throws FormatException if the value is invalid. + /// + public static bool ParseBool(string varName, bool defaultValue) + { + var value = Environment.GetEnvironmentVariable(varName); + if (string.IsNullOrEmpty(value)) + { + return defaultValue; + } + + if (bool.TryParse(value, out var result)) + { + return result; + } + + throw new FormatException($"Invalid boolean value for {varName}: got '{value}', expected 'true' or 'false'"); + } + + /// + /// Parses an enum environment variable value or returns the default if not set. + /// Enum values should be provided as strings matching enum names (case insensitive). + /// Throws ArgumentException if the value is invalid. + /// + public static T ParseEnum(string varName, T defaultValue, string[] validValues) where T : struct + { + var value = Environment.GetEnvironmentVariable(varName); + if (string.IsNullOrEmpty(value)) + { + return defaultValue; + } + + if (Enum.TryParse(value, ignoreCase: true, out var result)) + { + return result; + } + + var validValuesStr = string.Join(", ", validValues); + throw new ArgumentException($"Invalid value for {varName}: got '{value}', expected one of: {validValuesStr}"); + } +} diff --git a/sandbox/dotnet-server-sandbox/Configuration/PersistentStoreConfigurationBuilder.cs b/sandbox/dotnet-server-sandbox/Configuration/PersistentStoreConfigurationBuilder.cs new file mode 100644 index 00000000..95fdf8c3 --- /dev/null +++ b/sandbox/dotnet-server-sandbox/Configuration/PersistentStoreConfigurationBuilder.cs @@ -0,0 +1,109 @@ +using LaunchDarkly.Sdk.Server; +#if DEBUG_LOCAL_REFERENCES +using LaunchDarkly.Sdk.Server.Integrations; +#endif +using LaunchDarkly.Sdk.Server.Subsystems; + +namespace dotnet_server_test_app.Configuration; + +/// +/// Builds persistent store configurations (Redis or DynamoDB) from environment variables. +/// Note: Redis and DynamoDB support is only available when building with DebugLocalReferences configuration. +/// +internal static class PersistentStoreConfigurationBuilder +{ + /// + /// Builds a persistent store configuration based on LAUNCHDARKLY_PERSISTENT_STORE_TYPE environment variable. + /// Returns null if no persistent store is configured. + /// + internal static IComponentConfigurer? Build() + { + var storeType = Environment.GetEnvironmentVariable(EnvironmentVariables.PersistentStoreType); + + if (string.IsNullOrEmpty(storeType)) + { + return null; + } + + return storeType.ToLower() switch + { + "redis" => BuildRedisStore(), + "dynamodb" => BuildDynamoDBStore(), + _ => throw new ArgumentException( + $"Invalid persistent store type: got '{storeType}', expected one of: redis, dynamodb") + }; + } + +#if DEBUG_LOCAL_REFERENCES + /// + /// Builds a Redis persistent store configuration from environment variables. + /// + private static IComponentConfigurer BuildRedisStore() + { + var host = EnvironmentVariables.GetString(EnvironmentVariables.RedisHost, EnvironmentVariables.DefaultRedisHost); + var port = EnvironmentVariables.ParseInt(EnvironmentVariables.RedisPort, EnvironmentVariables.DefaultRedisPort); + var prefix = EnvironmentVariables.GetString(EnvironmentVariables.RedisPrefix, EnvironmentVariables.DefaultRedisPrefix); + var connectTimeoutMs = EnvironmentVariables.ParseInt( + EnvironmentVariables.RedisConnectTimeoutMs, + EnvironmentVariables.DefaultRedisConnectTimeoutMs); + var operationTimeoutMs = EnvironmentVariables.ParseInt( + EnvironmentVariables.RedisOperationTimeoutMs, + EnvironmentVariables.DefaultRedisOperationTimeoutMs); + + var redisBuilder = Redis.DataStore() + .HostAndPort(host, port) + .Prefix(prefix) + .ConnectTimeout(TimeSpan.FromMilliseconds(connectTimeoutMs)) + .OperationTimeout(TimeSpan.FromMilliseconds(operationTimeoutMs)); + + return Components.PersistentDataStore(redisBuilder); + } + + /// + /// Builds a DynamoDB persistent store configuration from environment variables. + /// + private static IComponentConfigurer BuildDynamoDBStore() + { + var tableName = Environment.GetEnvironmentVariable(EnvironmentVariables.DynamoDBTableName); + + if (string.IsNullOrEmpty(tableName)) + { + throw new InvalidOperationException( + $"{EnvironmentVariables.DynamoDBTableName} is required when using DynamoDB persistent store"); + } + + var prefix = EnvironmentVariables.GetString( + EnvironmentVariables.DynamoDBPrefix, + EnvironmentVariables.DefaultDynamoDBPrefix); + + var builder = DynamoDB.DataStore(tableName); + + if (!string.IsNullOrEmpty(prefix)) + { + builder.Prefix(prefix); + } + + return Components.PersistentDataStore(builder); + } +#else + /// + /// Stub for Redis store when not building with DebugLocalReferences. + /// + private static IComponentConfigurer? BuildRedisStore() + { + Console.WriteLine("WARNING: Redis persistent store is only available when building with DebugLocalReferences configuration."); + Console.WriteLine("Current build does not include Redis integration. Persistent store will not be used."); + return null; + } + + /// + /// Stub for DynamoDB store when not building with DebugLocalReferences. + /// + private static IComponentConfigurer? BuildDynamoDBStore() + { + Console.WriteLine("WARNING: DynamoDB persistent store is only available when building with DebugLocalReferences configuration."); + Console.WriteLine("Current build does not include DynamoDB integration. Persistent store will not be used."); + return null; + } +#endif +} diff --git a/sandbox/dotnet-server-sandbox/Configuration/SdkConfigurationBuilder.cs b/sandbox/dotnet-server-sandbox/Configuration/SdkConfigurationBuilder.cs new file mode 100644 index 00000000..318db12c --- /dev/null +++ b/sandbox/dotnet-server-sandbox/Configuration/SdkConfigurationBuilder.cs @@ -0,0 +1,60 @@ +using LaunchDarkly.Sdk.Server; + +namespace dotnet_server_test_app.Configuration; + +/// +/// Main configuration builder that reads environment variables and builds SDK configuration. +/// +public static class SdkConfigurationBuilder +{ + /// + /// Builds a LaunchDarkly SDK configuration from environment variables. + /// + /// A configured Configuration object ready for use with LdClient + /// Thrown when LAUNCHDARKLY_SDK_KEY is not set + /// Thrown when configuration is inconsistent + /// Thrown when an invalid value is provided + /// Thrown when a value cannot be parsed + public static LaunchDarkly.Sdk.Server.Configuration BuildFromEnvironment() + { + // 1. Validate SDK key exists (required) + var sdkKey = Environment.GetEnvironmentVariable(EnvironmentVariables.SdkKey); + if (string.IsNullOrEmpty(sdkKey)) + { + throw new ArgumentNullException( + EnvironmentVariables.SdkKey, + $"{EnvironmentVariables.SdkKey} environment variable is required"); + } + + // 2. Create configuration builder + var builder = LaunchDarkly.Sdk.Server.Configuration.Builder(sdkKey); + + // 3. Apply offline mode if specified + var offline = EnvironmentVariables.ParseBool( + EnvironmentVariables.Offline, + EnvironmentVariables.DefaultOffline); + if (offline) + { + builder.Offline(true); + } + + // 4. Apply DataSystem configuration (if not offline) + if (!offline) + { + var dataSystem = DataSystemConfigurationBuilder.Build(); + if (dataSystem != null) + { + builder.DataSystem(dataSystem); + } + } + + // 5. Apply start wait time + var startWaitTimeMs = EnvironmentVariables.ParseInt( + EnvironmentVariables.StartWaitTimeMs, + EnvironmentVariables.DefaultStartWaitTimeMs); + builder.StartWaitTime(TimeSpan.FromMilliseconds(startWaitTimeMs)); + + // 6. Build and return + return builder.Build(); + } +} diff --git a/sandbox/dotnet-server-sandbox/Program.cs b/sandbox/dotnet-server-sandbox/Program.cs new file mode 100644 index 00000000..a83bf573 --- /dev/null +++ b/sandbox/dotnet-server-sandbox/Program.cs @@ -0,0 +1,48 @@ +// See https://aka.ms/new-console-template for more information + +using dotnet_server_test_app.Configuration; +using LaunchDarkly.Sdk; +using LaunchDarkly.Sdk.Server; + +Configuration config; +try +{ + config = SdkConfigurationBuilder.BuildFromEnvironment(); +} +catch (Exception ex) +{ + Console.WriteLine($"Configuration Error: {ex.Message}"); + return 1; +} + +Console.WriteLine("Initializing client"); +var client = new LdClient(config); + +client.DataSourceStatusProvider.StatusChanged += (sender, status) => +{ + Console.WriteLine($"Status changed: {status}"); +}; + +client.DataStoreStatusProvider.StatusChanged += (sender, status) => +{ + Console.WriteLine($"Status changed: {status}"); +}; + +Console.WriteLine($"Data source status {client.DataSourceStatusProvider.Status}"); +Console.WriteLine($"Data store status {client.DataStoreStatusProvider.Status}"); + +Console.WriteLine($"Initialized: {client.Initialized}"); + +Console.WriteLine($"my-boolean-flag: {client.BoolVariation("my-boolean-flag", Context.New("bob"), false)}"); + +client.FlagTracker.FlagChanged += client.FlagTracker.FlagValueChangeHandler("my-boolean-flag", Context.New("bob"), + ((sender, @event) => { Console.WriteLine("Got change {0}, {1}", @event.Key, @event.NewValue); })); + +Console.WriteLine("Evaluate {0}", client.BoolVariation("my-boolean-flag", Context.New("bob"), false)); + +while (true) +{ + Console.ReadLine(); + + Console.WriteLine($"my-boolean-flag: {client.BoolVariation("my-boolean-flag", Context.New("bob"), false)}"); +} diff --git a/sandbox/dotnet-server-sandbox/README.md b/sandbox/dotnet-server-sandbox/README.md new file mode 100644 index 00000000..a3c17d5b --- /dev/null +++ b/sandbox/dotnet-server-sandbox/README.md @@ -0,0 +1,288 @@ +# LaunchDarkly .NET Server SDK Sandbox - Environment Variable Configuration + +This sandbox application supports configuration through environment variables, allowing you to test different SDK configurations. + +## Quick Start + +The minimal configuration requires only the SDK key: + +```bash +export LAUNCHDARKLY_SDK_KEY="your-sdk-key-here" +dotnet run +``` + +## Build Configuration Requirements + +### Persistent Store Support (Redis and DynamoDB) + +**Important:** Redis and DynamoDB persistent store integrations are only available when building with the `DebugLocalReferences` configuration. + +```bash +# Run with persistent store support +export LAUNCHDARKLY_SDK_KEY="your-sdk-key" +export LAUNCHDARKLY_DATA_SYSTEM_MODE="persistent-store" +export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis" +dotnet run --configuration DebugLocalReferences +``` + +**Why DebugLocalReferences?** + +This is required to be able to use local dependencies without building them with the strong-naming key. This project uses a project reference for the Server SDK and the persistent stores also need to be using a project reference. If they use the nuget references, then the strong naming requirement will prevent the project from building/running. + +**What works in other configurations (Debug/Release):** +- Default mode +- Streaming-only mode +- Polling-only mode +- Offline mode + +**What requires DebugLocalReferences:** +- Daemon mode (read-only from persistent store) +- Persistent-store mode (default + persistent store backup) + +If you attempt to use persistent store features without building with DebugLocalReferences, you'll see a clear warning message and the application will either fall back to in-memory storage or fail with an informative error. + +## Environment Variables Reference + +### Required Variables + +| Variable | Description | Example | +|----------|-------------|---------| +| `LAUNCHDARKLY_SDK_KEY` | Your LaunchDarkly SDK key (required) | `sdk-abc-123-xyz` | + +### Optional - Core Configuration + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `LAUNCHDARKLY_OFFLINE` | Boolean | `false` | Run SDK in offline mode (no connections to LaunchDarkly) | +| `LAUNCHDARKLY_DATA_SYSTEM_MODE` | Enum | `default` | Data acquisition strategy (see modes below) | +| `LAUNCHDARKLY_START_WAIT_TIME_MS` | Integer | `10000` | Maximum time (ms) to wait for SDK initialization | + +#### Data System Modes + +| Mode | Description | +|------|----------------------------------------------------| +| `default` | poll + streaming with polling fallback | +| `streaming` | Real-time streaming updates only | +| `polling` | Periodic polling only, no streaming | +| `daemon` | Read-only from persistent store | +| `persistent-store` | Default mode + persistent store backup | + +### Optional - Persistent Store Configuration + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `LAUNCHDARKLY_PERSISTENT_STORE_TYPE` | Enum | (none) | Type of persistent store: `redis` or `dynamodb` | + +**Note:** Required when using `daemon` or `persistent-store` data system modes. + +### Optional - Redis Configuration + +These variables apply when `LAUNCHDARKLY_PERSISTENT_STORE_TYPE=redis`: + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `LAUNCHDARKLY_REDIS_HOST` | String | `localhost` | Redis server hostname | +| `LAUNCHDARKLY_REDIS_PORT` | Integer | `6379` | Redis server port | +| `LAUNCHDARKLY_REDIS_PREFIX` | String | `launchdarkly` | Key prefix for all Redis keys | +| `LAUNCHDARKLY_REDIS_CONNECT_TIMEOUT_MS` | Integer | `5000` | Connection timeout in milliseconds | +| `LAUNCHDARKLY_REDIS_OPERATION_TIMEOUT_MS` | Integer | `3000` | Operation timeout in milliseconds | + +### Optional - DynamoDB Configuration + +These variables apply when `LAUNCHDARKLY_PERSISTENT_STORE_TYPE=dynamodb`: + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `LAUNCHDARKLY_DYNAMODB_TABLE_NAME` | String | (required) | DynamoDB table name (must exist) | +| `LAUNCHDARKLY_DYNAMODB_PREFIX` | String | `""` | Key prefix for DynamoDB items | + +**DynamoDB Table Requirements:** +- Partition key: `namespace` (String) +- Sort key: `key` (String) + +## Configuration Examples + +### 1. Default Mode (Recommended) + +Minimal configuration with just SDK key. Uses CDN + streaming: + +```bash +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +dotnet run +``` + +### 2. Offline Mode + +For testing without connecting to LaunchDarkly: + +```bash +export LAUNCHDARKLY_SDK_KEY="any-value" +export LAUNCHDARKLY_OFFLINE="true" +dotnet run +``` + +### 3. Redis Persistent Store + +Default mode backed by Redis persistent store: + +```bash +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +export LAUNCHDARKLY_DATA_SYSTEM_MODE="persistent-store" +export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis" +export LAUNCHDARKLY_REDIS_HOST="redis.example.com" +export LAUNCHDARKLY_REDIS_PORT="6379" +export LAUNCHDARKLY_REDIS_PREFIX="myapp:prod" +dotnet run +``` + +### 4. Daemon Mode with Redis + +Read-only mode for SDKs behind Relay Proxy: + +```bash +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +export LAUNCHDARKLY_DATA_SYSTEM_MODE="daemon" +export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis" +export LAUNCHDARKLY_REDIS_HOST="localhost" +export LAUNCHDARKLY_REDIS_PREFIX="ld:relay:prod" +dotnet run +``` + +### 5. DynamoDB Persistent Store + +Default mode backed by DynamoDB: + +```bash +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +export LAUNCHDARKLY_DATA_SYSTEM_MODE="persistent-store" +export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="dynamodb" +export LAUNCHDARKLY_DYNAMODB_TABLE_NAME="launchdarkly-features" +export LAUNCHDARKLY_DYNAMODB_PREFIX="myapp" +dotnet run +``` + +### 6. Streaming-Only Mode + +Real-time updates without CDN initialization: + +```bash +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +export LAUNCHDARKLY_DATA_SYSTEM_MODE="streaming" +dotnet run +``` + +### 7. Polling-Only Mode + +For restricted network environments: + +```bash +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +export LAUNCHDARKLY_DATA_SYSTEM_MODE="polling" +dotnet run +``` + +### 8. Custom Timeouts + +Adjust SDK behavior for slow networks: + +```bash +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +export LAUNCHDARKLY_START_WAIT_TIME_MS="30000" +export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis" +export LAUNCHDARKLY_REDIS_CONNECT_TIMEOUT_MS="10000" +export LAUNCHDARKLY_REDIS_OPERATION_TIMEOUT_MS="5000" +dotnet run +``` + +## Data System Modes Explained + +### Default Mode +**Use when:** You want LaunchDarkly's recommended configuration (best for most production scenarios) + +**How it works:** +1. Fetches initial data from global CDN (fast) +2. Establishes streaming connection for real-time updates +3. Falls back to polling if streaming is interrupted + +### Streaming Mode +**Use when:** You need real-time updates without CDN initialization delay + +**How it works:** +- Establishes streaming connection immediately +- Receives real-time updates as flags change +- Can fall back to polling if instructed by LaunchDarkly + +### Polling Mode +**Use when:** Your network doesn't support streaming (firewall restrictions, etc.) + +**How it works:** +- Periodically polls LaunchDarkly CDN for updates +- No real-time updates +- Predictable network traffic pattern + +### Daemon Mode +**Use when:** Multiple SDK instances need to share flag data via Relay Proxy + +**How it works:** +- SDK never connects to LaunchDarkly +- Reads flag data from persistent store (populated by Relay Proxy or another SDK) +- SDK never writes to the store (read-only) + +**Requirements:** Must configure `LAUNCHDARKLY_PERSISTENT_STORE_TYPE` + +### Persistent Store Mode +**Use when:** You want fast startup times and resilience to temporary network issues + +**How it works:** +- Uses default mode (CDN + streaming) +- Maintains a persistent store with latest flag data +- On startup, can serve flags from store while waiting for fresh data +- Keeps store up-to-date as new data arrives + +**Requirements:** Must configure `LAUNCHDARKLY_PERSISTENT_STORE_TYPE` + +## Troubleshooting + +### Error: "LAUNCHDARKLY_SDK_KEY environment variable is required" +**Solution:** Set the `LAUNCHDARKLY_SDK_KEY` environment variable before running the application. + +### Error: "Invalid data system mode" +**Solution:** Check that `LAUNCHDARKLY_DATA_SYSTEM_MODE` is set to one of: `default`, `streaming`, `polling`, `daemon`, or `persistent-store`. + +### Error: "daemon mode requires a persistent store" +**Solution:** When using daemon or persistent-store modes, you must set `LAUNCHDARKLY_PERSISTENT_STORE_TYPE` to either `redis` or `dynamodb`. + +### Error: "LAUNCHDARKLY_DYNAMODB_TABLE_NAME is required" +**Solution:** When using DynamoDB as the persistent store, you must specify the table name via `LAUNCHDARKLY_DYNAMODB_TABLE_NAME`. + +### Error: "Invalid integer value for..." +**Solution:** Ensure numeric environment variables (ports, timeouts) contain valid integer values. + +### Error: "Invalid boolean value for..." +**Solution:** Boolean environment variables must be set to either `true` or `false` (case-insensitive). + +## AWS Credentials for DynamoDB + +When using DynamoDB, the SDK uses the standard AWS credential chain: +1. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`) +2. Shared credentials file (`~/.aws/credentials`) +3. IAM role (when running on AWS infrastructure) + +Example with explicit credentials: +```bash +export AWS_ACCESS_KEY_ID="your-access-key" +export AWS_SECRET_ACCESS_KEY="your-secret-key" +export AWS_REGION="us-east-1" +export LAUNCHDARKLY_SDK_KEY="sdk-abc-123" +export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="dynamodb" +export LAUNCHDARKLY_DYNAMODB_TABLE_NAME="launchdarkly-flags" +dotnet run +``` + +## Boolean Values + +Boolean environment variables accept the following values (case-insensitive): +- True: `true`, `True`, `TRUE` +- False: `false`, `False`, `FALSE` + +Any other value will result in a format error. diff --git a/sandbox/dotnet-server-sandbox/dotnet-server-sandbox.csproj b/sandbox/dotnet-server-sandbox/dotnet-server-sandbox.csproj new file mode 100644 index 00000000..29afa44f --- /dev/null +++ b/sandbox/dotnet-server-sandbox/dotnet-server-sandbox.csproj @@ -0,0 +1,32 @@ + + + + Exe + net8.0 + dotnet_server_test_app + enable + enable + true + true + Debug;Release;DebugLocalReferences + AnyCPU + + + + + DEBUG_LOCAL_REFERENCES + + + + + + + + + + + + + + +