diff --git a/daprdocs/content/en/dotnet-sdk-docs/dotnet-development/dotnet-development-experimental-attributes.md b/daprdocs/content/en/dotnet-sdk-docs/dotnet-development/dotnet-development-experimental-attributes.md new file mode 100644 index 000000000..12825be20 --- /dev/null +++ b/daprdocs/content/en/dotnet-sdk-docs/dotnet-development/dotnet-development-experimental-attributes.md @@ -0,0 +1,138 @@ +--- +type: docs +title: "Dapr .NET SDK Development with Dapr CLI" +linkTitle: "Experimental Attributes" +weight: 61000 +description: Learn about local development with the Dapr CLI +--- + +## Experimental Attributes + +### Introduction to Experimental Attributes + +With the release of .NET 8, C# 12 introduced the `[Experimental]` attribute, which provides a standardized way to mark +APIs that are still in development or experimental. This attribute is defined in the `System.Diagnostics.CodeAnalysis` +namespace and requires a diagnostic ID parameter used to generate compiler warnings when the experimental API +is used. + +In the Dapr .NET SDK, we now use the `[Experimental]` attribute instead of `[Obsolete]` to mark building blocks and +components that have not yet passed the stable lifecycle certification. This approach provides a clearer distinction +between: + +1. **Experimental APIs** - Features that are available but still evolving and have not yet been certified as stable +according to the [Dapr Component Certification Lifecycle](https://docs.dapr.io/operations/components/certification-lifecycle/). + +2. **Obsolete APIs** - Features that are truly deprecated and will be removed in a future release. + +### Usage in the Dapr .NET SDK + +In the Dapr .NET SDK, we apply the `[Experimental]` attribute at the class level for building blocks that are still in +the Alpha or Beta stages of the [Component Certification Lifecycle](https://docs.dapr.io/operations/components/certification-lifecycle/). +The attribute includes: + +- A diagnostic ID that identifies the experimental building block +- A URL that points to the relevant documentation for that block + +For example: + +```csharp +using System.Diagnostics.CodeAnalysis; +namespace Dapr.Cryptography.Encryption +{ + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] + public class DaprEncryptionClient + { + // Implementation + } +} +``` + +The diagnostic IDs follow a naming convention of `DAPR_[BUILDING_BLOCK_NAME]`, such as: + +- `DAPR_CONVERSATION` - For the Conversation building block +- `DAPR_CRYPTOGRAPHY` - For the Cryptography building block +- `DAPR_JOBS` - For the Jobs building block +- `DAPR_DISTRIBUTEDLOCK` - For the Distributed Lock building block + +### Suppressing Experimental Warnings + +When you use APIs marked with the `[Experimental]` attribute, the compiler will generate errors. +To build your solution without marking your own code as experimental, you will need to suppress these errors. Here are +several approaches to do this: + +#### Option 1: Using #pragma directive + +You can use the `#pragma warning` directive to suppress the warning for specific sections of code: + +```csharp +// Disable experimental warning +#pragma warning disable DAPR_CRYPTOGRAPHY +// Your code using the experimental API +var client = new DaprEncryptionClient(); +// Re-enable the warning +#pragma warning restore DAPR_CRYPTOGRAPHY +``` + +This approach is useful when you want to suppress warnings only for specific sections of your code. + +#### Option 2: Project-level suppression + +To suppress warnings for an entire project, add the following to your `.csproj` file. +file. + +```xml + + $(NoWarn);DAPR_CRYPTOGRAPHY + +``` + +You can include multiple diagnostic IDs separated by semicolons: + +```xml + + $(NoWarn);DAPR_CONVERSATION;DAPR_JOBS;DAPR_DISTRIBUTEDLOCK;DAPR_CRYPTOGRAPHY + +``` + +This approach is particularly useful for test projects that need to use experimental APIs. + +#### Option 3: Directory-level suppression + +For suppressing warnings across multiple projects in a directory, add a `Directory.Build.props` file: + +```xml + + $(NoWarn);DAPR_CONVERSATION;DAPR_JOBS;DAPR_DISTRIBUTEDLOCK;DAPR_CRYPTOGRAPHY + +``` + +This file should be placed in the root directory of your test projects. You can learn more about using +`Directory.Build.props` files in the +[MSBuild documentation](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory). + +### Lifecycle of Experimental APIs + +As building blocks move through the certification lifecycle and reach the "Stable" stage, the `[Experimental]` attribute will be removed. No migration or code changes will be required from users when this happens, except for the removal of any warning suppressions if they were added. + +Conversely, the `[Obsolete]` attribute will now be reserved exclusively for APIs that are truly deprecated and scheduled for removal. When you see a method or class marked with `[Obsolete]`, you should plan to migrate away from it according to the migration guidance provided in the attribute message. + +### Best Practices + +1. **In application code:** + - Be cautious when using experimental APIs, as they may change in future releases + - Consider isolating usage of experimental APIs to make future updates easier + - Document your use of experimental APIs for team awareness + +2. **In test code:** + - Use project-level suppression to avoid cluttering test code with warning suppressions + - Regularly review which experimental APIs you're using and check if they've been stabilized + +3. **When contributing to the SDK:** + - Use `[Experimental]` for new building blocks that haven't completed certification + - Use `[Obsolete]` only for truly deprecated APIs + - Provide clear documentation links in the `UrlFormat` parameter + +### Additional Resources + +- [Dapr Component Certification Lifecycle](https://docs.dapr.io/operations/components/certification-lifecycle/) +- [C# Experimental Attribute Documentation](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-12.0/experimental-attribute) diff --git a/examples/Client/DistributedLock/Controllers/BindingController.cs b/examples/Client/DistributedLock/Controllers/BindingController.cs index 37fbe637b..64228df43 100644 --- a/examples/Client/DistributedLock/Controllers/BindingController.cs +++ b/examples/Client/DistributedLock/Controllers/BindingController.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json; using System.Threading.Tasks; @@ -11,24 +12,15 @@ namespace DistributedLock.Controllers; [ApiController] -public class BindingController : ControllerBase +[Experimental("DAPR_DISTRIBUTEDLOCK", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/")] +public class BindingController(DaprClient client, ILogger logger) : ControllerBase { - private DaprClient client; - private ILogger logger; - private string appId; - - public BindingController(DaprClient client, ILogger logger) - { - this.client = client; - this.logger = logger; - this.appId = Environment.GetEnvironmentVariable("APP_ID"); - } - + private string appId = Environment.GetEnvironmentVariable("APP_ID"); + [HttpPost("cronbinding")] - [Obsolete] public async Task HandleBindingEvent() { - logger.LogInformation($"Received binding event on {appId}, scanning for work."); + logger.LogInformation("Received binding event on {appId}, scanning for work.", appId); var request = new BindingRequest("localstorage", "list"); var result = client.InvokeBindingAsync(request); @@ -47,44 +39,40 @@ public async Task HandleBindingEvent() return Ok(); } - - [Obsolete] private async Task AttemptToProcessFile(string fileName) { // Locks are Disposable and will automatically unlock at the end of a 'using' statement. - logger.LogInformation($"Attempting to lock: {fileName}"); - await using (var fileLock = await client.Lock("redislock", fileName, appId, 60)) + logger.LogInformation("Attempting to lock: {fileName}", fileName); + await using var fileLock = await client.Lock("redislock", fileName, appId, 60); + if (fileLock.Success) { - if (fileLock.Success) - { - logger.LogInformation($"Successfully locked file: {fileName}"); + logger.LogInformation("Successfully locked file: {fileName}", fileName); - // Get the file after we've locked it, we're safe here because of the lock. - var fileState = await GetFile(fileName); + // Get the file after we've locked it, we're safe here because of the lock. + var fileState = await GetFile(fileName); - if (fileState == null) - { - logger.LogWarning($"File {fileName} has already been processed!"); - return; - } + if (fileState == null) + { + logger.LogWarning("File {fileName} has already been processed!", fileName); + return; + } - // "Analyze" the file before committing it to our remote storage. - fileState.Analysis = fileState.Number > 50 ? "High" : "Low"; + // "Analyze" the file before committing it to our remote storage. + fileState.Analysis = fileState.Number > 50 ? "High" : "Low"; - // Save it to remote storage. - await client.SaveStateAsync("redisstore", fileName, fileState); + // Save it to remote storage. + await client.SaveStateAsync("redisstore", fileName, fileState); - // Remove it from local storage. - var bindingDeleteRequest = new BindingRequest("localstorage", "delete"); - bindingDeleteRequest.Metadata["fileName"] = fileName; - await client.InvokeBindingAsync(bindingDeleteRequest); + // Remove it from local storage. + var bindingDeleteRequest = new BindingRequest("localstorage", "delete"); + bindingDeleteRequest.Metadata["fileName"] = fileName; + await client.InvokeBindingAsync(bindingDeleteRequest); - logger.LogInformation($"Done processing {fileName}"); - } - else - { - logger.LogWarning($"Failed to lock {fileName}."); - } + logger.LogInformation("Done processing {fileName}", fileName); + } + else + { + logger.LogWarning("Failed to lock {fileName}.", fileName); } } @@ -103,4 +91,4 @@ private async Task GetFile(string fileName) return null; } } -} \ No newline at end of file +} diff --git a/examples/Directory.Build.props b/examples/Directory.Build.props index 95483b7a0..0c8af6eaf 100644 --- a/examples/Directory.Build.props +++ b/examples/Directory.Build.props @@ -7,5 +7,6 @@ $(RepoRoot)bin\$(Configuration)\examples\$(MSBuildProjectName)\ false + $(NoWarn);DAPR_CONVERSATION;DAPR_JOBS;DAPR_DISTRIBUTEDLOCK;DAPR_CRYPTOGRAPHY \ No newline at end of file diff --git a/src/Dapr.AI/Conversation/DaprConversationClient.cs b/src/Dapr.AI/Conversation/DaprConversationClient.cs index b081427b0..a3bd58f89 100644 --- a/src/Dapr.AI/Conversation/DaprConversationClient.cs +++ b/src/Dapr.AI/Conversation/DaprConversationClient.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Autogenerated = Dapr.Client.Autogen.Grpc.v1.Dapr; namespace Dapr.AI.Conversation; @@ -30,6 +31,7 @@ namespace Dapr.AI.Conversation; /// exhaustion and other problems. /// /// +[Experimental("DAPR_CONVERSATION", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/")] public abstract class DaprConversationClient : DaprAIClient { /// diff --git a/src/Dapr.AI/Conversation/DaprConversationClientBuilder.cs b/src/Dapr.AI/Conversation/DaprConversationClientBuilder.cs index ae897fcde..a8a7983f1 100644 --- a/src/Dapr.AI/Conversation/DaprConversationClientBuilder.cs +++ b/src/Dapr.AI/Conversation/DaprConversationClientBuilder.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common; using Microsoft.Extensions.Configuration; using Autogenerated = Dapr.Client.Autogen.Grpc.v1.Dapr; @@ -21,6 +22,7 @@ namespace Dapr.AI.Conversation; /// Used to create a new instance of a . /// /// An optional to configure the client with. +[Experimental("DAPR_CONVERSATION", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/")] public sealed class DaprConversationClientBuilder(IConfiguration? configuration = null) : DaprGenericClientBuilder(configuration) { /// @@ -30,6 +32,7 @@ public sealed class DaprConversationClientBuilder(IConfiguration? configuration /// /// Builds the client instance from the properties of the builder. /// + [Experimental("DAPR_CONVERSATION", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/")] public override DaprConversationClient Build() { var daprClientDependencies = BuildDaprClientDependencies(typeof(DaprConversationClient).Assembly); diff --git a/src/Dapr.AI/Conversation/DaprConversationGrpcClient.cs b/src/Dapr.AI/Conversation/DaprConversationGrpcClient.cs index 6a1a5f438..a95dfd712 100644 --- a/src/Dapr.AI/Conversation/DaprConversationGrpcClient.cs +++ b/src/Dapr.AI/Conversation/DaprConversationGrpcClient.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common; using Dapr.Common.Extensions; using Autogenerated = Dapr.Client.Autogen.Grpc.v1; @@ -23,6 +24,7 @@ namespace Dapr.AI.Conversation; /// The Dapr client. /// The HTTP client used by the client for calling the Dapr runtime. /// An optional token required to send requests to the Dapr sidecar. +[Experimental("DAPR_CONVERSATION", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/")] internal sealed class DaprConversationGrpcClient(Autogenerated.Dapr.DaprClient client, HttpClient httpClient, string? daprApiToken = null) : DaprConversationClient(client, httpClient, daprApiToken: daprApiToken) { /// diff --git a/src/Dapr.AI/Conversation/Extensions/DaprAiConversationBuilderExtensions.cs b/src/Dapr.AI/Conversation/Extensions/DaprAiConversationBuilderExtensions.cs index 42bd91804..ba7c7b914 100644 --- a/src/Dapr.AI/Conversation/Extensions/DaprAiConversationBuilderExtensions.cs +++ b/src/Dapr.AI/Conversation/Extensions/DaprAiConversationBuilderExtensions.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common.Extensions; using Microsoft.Extensions.DependencyInjection; @@ -24,6 +25,7 @@ public static class DaprAiConversationBuilderExtensions /// /// Registers the necessary functionality for the Dapr AI Conversation functionality. /// + [Experimental("DAPR_CONVERSATION", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/")] public static IDaprAiConversationBuilder AddDaprConversationClient( this IServiceCollection services, Action? configure = null, diff --git a/src/Dapr.Client/DaprClient.cs b/src/Dapr.Client/DaprClient.cs index 96fe0cfde..3e614324d 100644 --- a/src/Dapr.Client/DaprClient.cs +++ b/src/Dapr.Client/DaprClient.cs @@ -14,6 +14,7 @@ #nullable enable using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net.Http; @@ -1089,7 +1090,7 @@ public abstract Task UnsubscribeConfiguration( /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public abstract Task> EncryptAsync(string vaultResourceName, ReadOnlyMemory plaintextBytes, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default); @@ -1103,7 +1104,7 @@ public abstract Task> EncryptAsync(string vaultResourceName /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public abstract Task>> EncryptAsync(string vaultResourceName, Stream plaintextStream, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default); @@ -1116,7 +1117,7 @@ public abstract Task>> EncryptAsync(string /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An array of decrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public abstract Task> DecryptAsync(string vaultResourceName, ReadOnlyMemory ciphertextBytes, string keyName, DecryptionOptions options, CancellationToken cancellationToken = default); @@ -1128,7 +1129,7 @@ public abstract Task> DecryptAsync(string vaultResourceName /// The name of the key to use from the Vault for the decryption operation. /// A that can be used to cancel the operation. /// An array of decrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public abstract Task> DecryptAsync(string vaultResourceName, ReadOnlyMemory ciphertextBytes, string keyName, CancellationToken cancellationToken = default); @@ -1141,8 +1142,7 @@ public abstract Task> DecryptAsync(string vaultResourceName /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An asynchronously enumerable array of decrypted bytes. - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public abstract Task>> DecryptAsync(string vaultResourceName, Stream ciphertextStream, string keyName, DecryptionOptions options, CancellationToken cancellationToken = default); @@ -1154,8 +1154,7 @@ public abstract Task>> DecryptAsync(string /// The name of the key to use from the Vault for the decryption operation. /// A that can be used to cancel the operation. /// An asynchronously enumerable array of decrypted bytes. - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public abstract Task>> DecryptAsync(string vaultResourceName, Stream ciphertextStream, string keyName, CancellationToken cancellationToken = default); @@ -1171,7 +1170,7 @@ public abstract Task>> DecryptAsync(string ///// The format to use for the key result. ///// A that can be used to cancel the operation. ///// The name (and possibly version as name/version) of the key and its public key. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public abstract Task<(string Name, string PublicKey)> GetKeyAsync(string vaultResourceName, string keyName, SubtleGetKeyRequest.Types.KeyFormat keyFormat, // CancellationToken cancellationToken = default); @@ -1186,7 +1185,7 @@ public abstract Task>> DecryptAsync(string ///// Any associated data when using AEAD ciphers. ///// A that can be used to cancel the operation. ///// The array of encrypted bytes. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public abstract Task<(byte[] CipherTextBytes, byte[] AuthenticationTag)> EncryptAsync( // string vaultResourceName, // byte[] plainTextBytes, @@ -1206,7 +1205,7 @@ public abstract Task>> DecryptAsync(string ///// The bytes comprising the nonce. ///// A that can be used to cancel the operation. ///// The array of encrypted bytes. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public async Task<(byte[] CipherTextBytes, byte[] AuthenticationTag)> EncryptAsync( // string vaultResourceName, // byte[] plainTextBytes, @@ -1229,7 +1228,7 @@ public abstract Task>> DecryptAsync(string ///// ///// Any associated data when using AEAD ciphers. ///// The array of plaintext bytes. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public abstract Task DecryptAsync(string vaultResourceName, byte[] cipherTextBytes, // string algorithm, string keyName, byte[] nonce, byte[] tag, byte[] associatedData, // CancellationToken cancellationToken = default); @@ -1245,8 +1244,7 @@ public abstract Task>> DecryptAsync(string ///// The nonce value used. ///// ///// The array of plaintext bytes. - //[Obsolete( - // "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public async Task DecryptAsync(string vaultResourceName, byte[] cipherTextBytes, // string algorithm, string keyName, byte[] nonce, byte[] tag, CancellationToken cancellationToken = default) => // await DecryptAsync(vaultResourceName, cipherTextBytes, algorithm, keyName, nonce, tag, Array.Empty(), cancellationToken); @@ -1262,7 +1260,7 @@ public abstract Task>> DecryptAsync(string ///// Any associated data when using AEAD ciphers. ///// A that can be used to cancel the operation. ///// The bytes comprising the wrapped plain-text key and the authentication tag, if applicable. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public abstract Task<(byte[] WrappedKey, byte[] AuthenticationTag)> WrapKeyAsync(string vaultResourceName, byte[] plainTextKey, string keyName, string algorithm, byte[] nonce, byte[] associatedData, // CancellationToken cancellationToken = default); @@ -1276,7 +1274,7 @@ public abstract Task>> DecryptAsync(string ///// The none used. ///// A that can be used to cancel the operation. ///// The bytes comprising the unwrapped key and the authentication tag, if applicable. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public async Task<(byte[] WrappedKey, byte[] AuthenticationTag)> WrapKeyAsync(string vaultResourceName, byte[] plainTextKey, string keyName, string algorithm, // byte[] nonce, CancellationToken cancellationToken = default) => await WrapKeyAsync(vaultResourceName, plainTextKey, // keyName, algorithm, nonce, Array.Empty(), cancellationToken); @@ -1293,7 +1291,7 @@ public abstract Task>> DecryptAsync(string ///// Any associated data when using AEAD ciphers. ///// A that can be used to cancel the operation. ///// The bytes comprising the unwrapped key. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public abstract Task UnwrapKeyAsync(string vaultResourceName, byte[] wrappedKey, string algorithm, string keyName, byte[] nonce, byte[] tag, byte[] associatedData, // CancellationToken cancellationToken = default); @@ -1308,7 +1306,7 @@ public abstract Task>> DecryptAsync(string ///// The bytes comprising the authentication tag. ///// A that can be used to cancel the operation. ///// The bytes comprising the unwrapped key. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public async Task UnwrapKeyAsync(string vaultResourceName, byte[] wrappedKey, string algorithm, string keyName, // byte[] nonce, byte[] tag, // CancellationToken cancellationToken = default) => await UnwrapKeyAsync(vaultResourceName, @@ -1324,7 +1322,7 @@ public abstract Task>> DecryptAsync(string ///// The nonce value. ///// A that can be used to cancel the operation. ///// The bytes comprising the unwrapped key. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public async Task UnwrapKeyAsync(string vaultResourceName, byte[] wrappedKey, string algorithm, string keyName, // byte[] nonce, CancellationToken cancellationToken = default) => await UnwrapKeyAsync(vaultResourceName, // wrappedKey, algorithm, keyName, nonce, Array.Empty(), Array.Empty(), cancellationToken); @@ -1338,7 +1336,7 @@ public abstract Task>> DecryptAsync(string ///// The name of the key used. ///// A that can be used to cancel the operation. ///// The bytes comprising the signature. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public abstract Task SignAsync(string vaultResourceName, byte[] digest, string algorithm, string keyName, // CancellationToken cancellationToken = default); @@ -1352,12 +1350,14 @@ public abstract Task>> DecryptAsync(string ///// The name of the key used. ///// A that can be used to cancel the operation. ///// True if the signature verification is successful; otherwise false. - //[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public abstract Task VerifyAsync(string vaultResourceName, byte[] digest, byte[] signature, string algorithm, string keyName, // CancellationToken cancellationToken = default); #endregion + #region Distributed Lock + /// /// Attempt to lock the given resourceId with response indicating success. /// @@ -1367,7 +1367,7 @@ public abstract Task>> DecryptAsync(string /// The time after which the lock gets expired. /// A that can be used to cancel the operation. /// A containing a - [Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_DISTRIBUTEDLOCK", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/")] public abstract Task Lock( string storeName, string resourceId, @@ -1384,12 +1384,14 @@ public abstract Task Lock( /// Indicates the identifier of lock owner. /// A that can be used to cancel the operation. /// A containing a - [Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_DISTRIBUTEDLOCK", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/")] public abstract Task Unlock( string storeName, string resourceId, string lockOwner, CancellationToken cancellationToken = default); + + #endregion /// public void Dispose() diff --git a/src/Dapr.Client/DaprClientGrpc.cs b/src/Dapr.Client/DaprClientGrpc.cs index 70fe750af..50f048ad2 100644 --- a/src/Dapr.Client/DaprClientGrpc.cs +++ b/src/Dapr.Client/DaprClientGrpc.cs @@ -11,6 +11,8 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; + namespace Dapr.Client; using System; @@ -1666,8 +1668,7 @@ public override async Task UnsubscribeConfigur #region Cryptography /// - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public override async Task> EncryptAsync(string vaultResourceName, ReadOnlyMemory plaintextBytes, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default) @@ -1687,8 +1688,7 @@ public override async Task> EncryptAsync(string vaultResour } /// - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public override async Task>> EncryptAsync(string vaultResourceName, Stream plaintextStream, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default) @@ -1734,7 +1734,7 @@ public override async Task>> EncryptAsync( /// /// Sends the plaintext bytes in chunks to the sidecar to be encrypted. /// - private async Task SendPlaintextStreamAsync(Stream plaintextStream, + private static async Task SendPlaintextStreamAsync(Stream plaintextStream, int streamingBlockSizeInBytes, AsyncDuplexStreamingCall duplexStream, Autogenerated.EncryptRequestOptions encryptRequestOptions, @@ -1777,7 +1777,7 @@ await duplexStream.RequestStream.WriteAsync( /// /// Retrieves the encrypted bytes from the encryption operation on the sidecar and returns as an enumerable stream. /// - private async IAsyncEnumerable> RetrieveEncryptedStreamAsync( + private static async IAsyncEnumerable> RetrieveEncryptedStreamAsync( AsyncDuplexStreamingCall duplexStream, [EnumeratorCancellation] CancellationToken cancellationToken) { @@ -1789,8 +1789,7 @@ private async IAsyncEnumerable> RetrieveEncryptedStreamAsyn } /// - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public override async Task>> DecryptAsync(string vaultResourceName, Stream ciphertextStream, string keyName, DecryptionOptions decryptionOptions, CancellationToken cancellationToken = default) @@ -1821,8 +1820,7 @@ public override async Task>> DecryptAsync( } /// - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public override Task>> DecryptAsync(string vaultResourceName, Stream ciphertextStream, string keyName, CancellationToken cancellationToken = default) => DecryptAsync(vaultResourceName, ciphertextStream, keyName, new DecryptionOptions(), @@ -1831,7 +1829,7 @@ public override Task>> DecryptAsync(string /// /// Sends the ciphertext bytes in chunks to the sidecar to be decrypted. /// - private async Task SendCiphertextStreamAsync(Stream ciphertextStream, + private static async Task SendCiphertextStreamAsync(Stream ciphertextStream, int streamingBlockSizeInBytes, AsyncDuplexStreamingCall duplexStream, Autogenerated.DecryptRequestOptions decryptRequestOptions, @@ -1873,7 +1871,7 @@ await duplexStream.RequestStream.WriteAsync( /// /// Retrieves the decrypted bytes from the decryption operation on the sidecar and returns as an enumerable stream. /// - private async IAsyncEnumerable> RetrieveDecryptedStreamAsync( + private static async IAsyncEnumerable> RetrieveDecryptedStreamAsync( AsyncDuplexStreamingCall duplexStream, [EnumeratorCancellation] CancellationToken cancellationToken) { @@ -1885,8 +1883,7 @@ private async IAsyncEnumerable> RetrieveDecryptedStreamAsyn } /// - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public override async Task> DecryptAsync(string vaultResourceName, ReadOnlyMemory ciphertextBytes, string keyName, DecryptionOptions decryptionOptions, CancellationToken cancellationToken = default) @@ -1906,8 +1903,7 @@ public override async Task> DecryptAsync(string vaultResour } /// - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + [Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public override async Task> DecryptAsync(string vaultResourceName, ReadOnlyMemory ciphertextBytes, string keyName, CancellationToken cancellationToken = default) => await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, @@ -1916,7 +1912,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, #region Subtle Crypto Implementation ///// - //[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public override async Task<(string Name, string PublicKey)> GetKeyAsync(string vaultResourceName, string keyName, Autogenerated.SubtleGetKeyRequest.Types.KeyFormat keyFormat, // CancellationToken cancellationToken = default) //{ @@ -1945,7 +1941,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, //} ///// - //[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public override async Task<(byte[] CipherTextBytes, byte[] AuthenticationTag)> EncryptAsync(string vaultResourceName, byte[] plainTextBytes, string algorithm, // string keyName, byte[] nonce, byte[] associatedData, CancellationToken cancellationToken = default) //{ @@ -1981,7 +1977,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, //} ///// - //[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public override async Task DecryptAsync(string vaultResourceName, byte[] cipherTextBytes, string algorithm, string keyName, byte[] nonce, byte[] tag, // byte[] associatedData, CancellationToken cancellationToken = default) //{ @@ -2017,7 +2013,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, //} ///// - //[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public override async Task<(byte[] WrappedKey, byte[] AuthenticationTag)> WrapKeyAsync(string vaultResourceName, byte[] plainTextKey, string keyName, // string algorithm, byte[] nonce, byte[] associatedData, CancellationToken cancellationToken = default) //{ @@ -2053,7 +2049,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, //} ///// - //[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public override async Task UnwrapKeyAsync(string vaultResourceName, byte[] wrappedKey, string algorithm, // string keyName, byte[] nonce, byte[] tag, byte[] associatedData, CancellationToken cancellationToken = default) //{ @@ -2090,7 +2086,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, //} ///// - //[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public override async Task SignAsync(string vaultResourceName, byte[] digest, string algorithm, string keyName, CancellationToken cancellationToken = default) //{ // ArgumentVerifier.ThrowIfNullOrEmpty(vaultResourceName, nameof(vaultResourceName)); @@ -2123,7 +2119,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, //} ///// - //[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] + //[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] //public override async Task VerifyAsync(string vaultResourceName, byte[] digest, byte[] signature, // string algorithm, string keyName, CancellationToken cancellationToken = default) //{ @@ -2165,7 +2161,7 @@ await DecryptAsync(vaultResourceName, ciphertextBytes, keyName, #region Distributed Lock API /// - [Obsolete] + [Experimental("DAPR_DISTRIBUTEDLOCK", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/")] public async override Task Lock( string storeName, string resourceId, @@ -2205,7 +2201,7 @@ public async override Task Lock( } /// - [Obsolete] + [Experimental("DAPR_DISTRIBUTEDLOCK", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/")] public async override Task Unlock( string storeName, string resourceId, diff --git a/src/Dapr.Client/TryLockResponse.cs b/src/Dapr.Client/TryLockResponse.cs index 086eafc19..e341f91e0 100644 --- a/src/Dapr.Client/TryLockResponse.cs +++ b/src/Dapr.Client/TryLockResponse.cs @@ -12,6 +12,7 @@ // ------------------------------------------------------------------------ using System; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; namespace Dapr.Client; @@ -19,7 +20,7 @@ namespace Dapr.Client; /// /// Class representing the response from a Lock API call. /// -[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] +[Experimental("DAPR_DISTRIBUTEDLOCK", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/")] public sealed class TryLockResponse : IAsyncDisposable { /// diff --git a/src/Dapr.Cryptography/Encryption/DaprEncryptionClient.cs b/src/Dapr.Cryptography/Encryption/DaprEncryptionClient.cs index c99ed5718..a62ef39e7 100644 --- a/src/Dapr.Cryptography/Encryption/DaprEncryptionClient.cs +++ b/src/Dapr.Cryptography/Encryption/DaprEncryptionClient.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Cryptography.Encryption.Models; using Autogenerated = Dapr.Client.Autogen.Grpc.v1.Dapr; @@ -31,6 +32,7 @@ namespace Dapr.Cryptography.Encryption; /// exhaustion and other problems. /// /// +[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public abstract class DaprEncryptionClient(Autogenerated.DaprClient client, HttpClient httpClient, string? daprApiToken = null) : IDaprEncryptionClient { private bool disposed; @@ -68,7 +70,6 @@ public abstract class DaprEncryptionClient(Autogenerated.DaprClient client, Http /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public abstract Task> EncryptAsync(string vaultResourceName, ReadOnlyMemory plaintextBytes, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default); @@ -82,7 +83,6 @@ public abstract Task> EncryptAsync(string vaultResourceName /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public abstract IAsyncEnumerable> EncryptAsync(string vaultResourceName, Stream plaintextStream, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default); @@ -95,7 +95,6 @@ public abstract IAsyncEnumerable> EncryptAsync(string vault /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An array of decrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public abstract Task> DecryptAsync(string vaultResourceName, ReadOnlyMemory ciphertextBytes, string keyName, DecryptionOptions? options = null, CancellationToken cancellationToken = default); @@ -108,8 +107,6 @@ public abstract Task> DecryptAsync(string vaultResourceName /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An asynchronously enumerable array of decrypted bytes. - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public abstract IAsyncEnumerable> DecryptAsync(string vaultResourceName, Stream ciphertextStream, string keyName, DecryptionOptions? options = null, CancellationToken cancellationToken = default); diff --git a/src/Dapr.Cryptography/Encryption/DaprEncryptionClientBuilder.cs b/src/Dapr.Cryptography/Encryption/DaprEncryptionClientBuilder.cs index 65ff23917..833a849f3 100644 --- a/src/Dapr.Cryptography/Encryption/DaprEncryptionClientBuilder.cs +++ b/src/Dapr.Cryptography/Encryption/DaprEncryptionClientBuilder.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common; using Microsoft.Extensions.Configuration; using Autogenerated = Dapr.Client.Autogen.Grpc.v1; @@ -21,6 +22,7 @@ namespace Dapr.Cryptography.Encryption; /// Builds a . /// /// An optional instance of . +[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public sealed class DaprEncryptionClientBuilder(IConfiguration? configuration = null) : DaprGenericClientBuilder(configuration) { /// diff --git a/src/Dapr.Cryptography/Encryption/DaprEncryptionGrpcClient.cs b/src/Dapr.Cryptography/Encryption/DaprEncryptionGrpcClient.cs index c2d00fed0..271e2fba0 100644 --- a/src/Dapr.Cryptography/Encryption/DaprEncryptionGrpcClient.cs +++ b/src/Dapr.Cryptography/Encryption/DaprEncryptionGrpcClient.cs @@ -12,6 +12,7 @@ // ------------------------------------------------------------------------ using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Dapr.Common; using Dapr.Cryptography.Extensions; @@ -24,6 +25,7 @@ namespace Dapr.Cryptography.Encryption; /// /// A client for performing cryptography operations with Dapr. /// +[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] internal sealed class DaprEncryptionGrpcClient(Autogenerated.Dapr.DaprClient client, HttpClient httpClient, string? daprApiToken = null) : DaprEncryptionClient(client, httpClient, daprApiToken: daprApiToken) { /// @@ -35,7 +37,6 @@ internal sealed class DaprEncryptionGrpcClient(Autogenerated.Dapr.DaprClient cli /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public override async Task> EncryptAsync( string vaultResourceName, ReadOnlyMemory plaintextBytes, @@ -64,8 +65,6 @@ public override async Task> EncryptAsync( /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public override async IAsyncEnumerable> EncryptAsync( string vaultResourceName, Stream plaintextStream, @@ -132,7 +131,6 @@ await streamProcessor.ProcessStreamAsync(plaintextStream, duplexStream, encryptR /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An array of decrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public override async Task> DecryptAsync( string vaultResourceName, ReadOnlyMemory ciphertextBytes, @@ -161,8 +159,6 @@ public override async Task> DecryptAsync( /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An asynchronously enumerable array of decrypted bytes. - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public override async IAsyncEnumerable> DecryptAsync( string vaultResourceName, Stream ciphertextStream, diff --git a/src/Dapr.Cryptography/Encryption/Extensions/DaprCryptographyServiceCollectionExtensions.cs b/src/Dapr.Cryptography/Encryption/Extensions/DaprCryptographyServiceCollectionExtensions.cs index 152bbab4e..825591104 100644 --- a/src/Dapr.Cryptography/Encryption/Extensions/DaprCryptographyServiceCollectionExtensions.cs +++ b/src/Dapr.Cryptography/Encryption/Extensions/DaprCryptographyServiceCollectionExtensions.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common.Extensions; using Microsoft.Extensions.DependencyInjection; @@ -19,6 +20,7 @@ namespace Dapr.Cryptography.Encryption.Extensions; /// /// Contains extension methods for using Dapr cryptography with dependency injection. /// +[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public static class DaprCryptographyServiceCollectionExtensions { /// diff --git a/src/Dapr.Cryptography/Encryption/IDaprEncryptionClient.cs b/src/Dapr.Cryptography/Encryption/IDaprEncryptionClient.cs index ef2f21280..e7a10960d 100644 --- a/src/Dapr.Cryptography/Encryption/IDaprEncryptionClient.cs +++ b/src/Dapr.Cryptography/Encryption/IDaprEncryptionClient.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common; using Dapr.Cryptography.Encryption.Models; @@ -19,6 +20,7 @@ namespace Dapr.Cryptography.Encryption; /// /// Provides the implementation shape for the Dapr encryption client. /// +[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")] public interface IDaprEncryptionClient : IDaprClient { /// @@ -30,7 +32,6 @@ public interface IDaprEncryptionClient : IDaprClient /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public Task> EncryptAsync(string vaultResourceName, ReadOnlyMemory plaintextBytes, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default); @@ -44,7 +45,6 @@ public Task> EncryptAsync(string vaultResourceName, /// Options informing how the encryption operation should be configured. /// A that can be used to cancel the operation. /// An array of encrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public IAsyncEnumerable> EncryptAsync(string vaultResourceName, Stream plaintextStream, string keyName, EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default); @@ -57,7 +57,6 @@ public IAsyncEnumerable> EncryptAsync(string vaultResourceN /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An array of decrypted bytes. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public Task> DecryptAsync(string vaultResourceName, ReadOnlyMemory ciphertextBytes, string keyName, DecryptionOptions? options = null, CancellationToken cancellationToken = default); @@ -70,8 +69,6 @@ public Task> DecryptAsync(string vaultResourceName, ReadOnl /// Options informing how the decryption operation should be configured. /// A that can be used to cancel the operation. /// An asynchronously enumerable array of decrypted bytes. - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public IAsyncEnumerable> DecryptAsync(string vaultResourceName, Stream ciphertextStream, string keyName, DecryptionOptions? options = null, CancellationToken cancellationToken = default); } diff --git a/src/Dapr.Jobs/DaprJobsClient.cs b/src/Dapr.Jobs/DaprJobsClient.cs index c30c34ba3..2173a3ba1 100644 --- a/src/Dapr.Jobs/DaprJobsClient.cs +++ b/src/Dapr.Jobs/DaprJobsClient.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common; using Dapr.Jobs.Models; using Dapr.Jobs.Models.Responses; @@ -33,6 +34,7 @@ namespace Dapr.Jobs; /// exhaustion and other problems. /// /// +[Experimental("DAPR_JOBS", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/jobs/jobs-overview/")] public abstract class DaprJobsClient(Autogenerated.DaprClient client, HttpClient httpClient, string? daprApiToken = null) : IDaprClient { private bool disposed; @@ -74,8 +76,6 @@ public abstract class DaprJobsClient(Autogenerated.DaprClient client, HttpClient /// to require that an existing job with the same name be deleted first. /// The characteristics of the policy to apply when a job fails to trigger. /// Cancellation token. - [Obsolete( - "The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public abstract Task ScheduleJobAsync(string jobName, DaprJobSchedule schedule, ReadOnlyMemory? payload = null, DateTimeOffset? startingFrom = null, int? repeats = null, DateTimeOffset? ttl = null, bool overwrite = false, IJobFailurePolicyOptions? failurePolicyOptions = null, @@ -87,7 +87,6 @@ public abstract Task ScheduleJobAsync(string jobName, DaprJobSchedule schedule, /// The jobName of the job. /// Cancellation token. /// The details comprising the job. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public abstract Task GetJobAsync(string jobName, CancellationToken cancellationToken = default); /// @@ -95,7 +94,6 @@ public abstract Task ScheduleJobAsync(string jobName, DaprJobSchedule schedule, /// /// The jobName of the job. /// Cancellation token. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public abstract Task DeleteJobAsync(string jobName, CancellationToken cancellationToken = default); internal static KeyValuePair? GetDaprApiTokenHeader(string apiToken) diff --git a/src/Dapr.Jobs/DaprJobsClientBuilder.cs b/src/Dapr.Jobs/DaprJobsClientBuilder.cs index 12a66a892..979f7fb8a 100644 --- a/src/Dapr.Jobs/DaprJobsClientBuilder.cs +++ b/src/Dapr.Jobs/DaprJobsClientBuilder.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common; using Microsoft.Extensions.Configuration; using Autogenerated = Dapr.Client.Autogen.Grpc.v1; @@ -21,6 +22,7 @@ namespace Dapr.Jobs; /// Builds a . /// /// An optional instance of . +[Experimental("DAPR_JOBS", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/jobs/jobs-overview/")] public sealed class DaprJobsClientBuilder(IConfiguration? configuration = null) : DaprGenericClientBuilder(configuration) { /// diff --git a/src/Dapr.Jobs/DaprJobsGrpcClient.cs b/src/Dapr.Jobs/DaprJobsGrpcClient.cs index 31811ee82..245afdaae 100644 --- a/src/Dapr.Jobs/DaprJobsGrpcClient.cs +++ b/src/Dapr.Jobs/DaprJobsGrpcClient.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common; using Dapr.Jobs.Models; using Dapr.Jobs.Models.Responses; @@ -24,6 +25,7 @@ namespace Dapr.Jobs; /// /// A client for interacting with the Dapr endpoints. /// +[Experimental("DAPR_JOBS", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/jobs/jobs-overview/")] internal sealed class DaprJobsGrpcClient(Autogenerated.Dapr.DaprClient client, HttpClient httpClient, string? daprApiToken = null) : DaprJobsClient(client, httpClient, daprApiToken: daprApiToken) { /// @@ -38,7 +40,6 @@ internal sealed class DaprJobsGrpcClient(Autogenerated.Dapr.DaprClient client, H /// A flag indicating whether the job should be overwritten when submitted (true); otherwise false to require that an existing job with the same name be deleted first. /// The characteristics of the policy to apply when a job fails to trigger. /// Cancellation token. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public override async Task ScheduleJobAsync(string jobName, DaprJobSchedule schedule, ReadOnlyMemory? payload = null, DateTimeOffset? startingFrom = null, int? repeats = null, DateTimeOffset? ttl = null, bool overwrite = false, IJobFailurePolicyOptions? failurePolicyOptions = null, @@ -157,7 +158,6 @@ public override async Task ScheduleJobAsync(string jobName, DaprJobSchedule sche /// The name of the job. /// Cancellation token. /// The details comprising the job. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public override async Task GetJobAsync(string jobName, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(jobName)) @@ -205,7 +205,6 @@ public override async Task GetJobAsync(string jobName, Cancellat /// The name of the job. /// Cancellation token. /// - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public override async Task DeleteJobAsync(string jobName, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(jobName)) diff --git a/src/Dapr.Jobs/Extensions/DaprJobsServiceCollectionExtensions.cs b/src/Dapr.Jobs/Extensions/DaprJobsServiceCollectionExtensions.cs index 7eed80abc..3103e072b 100644 --- a/src/Dapr.Jobs/Extensions/DaprJobsServiceCollectionExtensions.cs +++ b/src/Dapr.Jobs/Extensions/DaprJobsServiceCollectionExtensions.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using Dapr.Common.Extensions; using Microsoft.Extensions.DependencyInjection; @@ -19,6 +20,7 @@ namespace Dapr.Jobs.Extensions; /// /// Contains extension methods for using Dapr Jobs with dependency injection. /// +[Experimental("DAPR_JOBS", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/jobs/jobs-overview/")] public static class DaprJobsServiceCollectionExtensions { /// diff --git a/src/Dapr.Jobs/Extensions/DaprSerializationExtensions.cs b/src/Dapr.Jobs/Extensions/DaprSerializationExtensions.cs index 2fd278002..fb58ef697 100644 --- a/src/Dapr.Jobs/Extensions/DaprSerializationExtensions.cs +++ b/src/Dapr.Jobs/Extensions/DaprSerializationExtensions.cs @@ -11,6 +11,7 @@ // limitations under the License. // ------------------------------------------------------------------------ +using System.Diagnostics.CodeAnalysis; using System.Text; using System.Text.Json; using Dapr.Jobs.Models; @@ -20,6 +21,7 @@ namespace Dapr.Jobs.Extensions; /// /// Provides helper extensions for performing serialization operations when scheduling one-time Cron jobs for the developer. /// +[Experimental("DAPR_JOBS", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/jobs/jobs-overview/")] public static class DaprJobsSerializationExtensions { /// @@ -41,7 +43,6 @@ public static class DaprJobsSerializationExtensions /// A flag indicating whether the job should be overwritten when submitted (true); otherwise false to require that an existing job with the same name be deleted first. /// The characteristics of the policy to apply when a job fails to trigger. /// Cancellation token. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public static async Task ScheduleJobWithPayloadAsync(this DaprJobsClient client, string jobName, DaprJobSchedule schedule, object payload, DateTime? startingFrom = null, int? repeats = null, JsonSerializerOptions? jsonSerializerOptions = null, DateTimeOffset? ttl = null, @@ -71,7 +72,6 @@ await client.ScheduleJobAsync(jobName, schedule, payloadBytes, startingFrom, rep /// A flag indicating whether the job should be overwritten when submitted (true); otherwise false to require that an existing job with the same name be deleted first. /// The characteristics of the policy to apply when a job fails to trigger. /// Cancellation token. - [Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")] public static async Task ScheduleJobWithPayloadAsync(this DaprJobsClient client, string jobName, DaprJobSchedule schedule, string payload, DateTime? startingFrom = null, int? repeats = null, DateTimeOffset? ttl = null, bool overwrite = false, IJobFailurePolicyOptions? failurePolicyOptions = null, diff --git a/test/Dapr.Jobs.Analyzer.Test/MapDaprScheduledJobHandlerTest.cs b/test/Dapr.Jobs.Analyzer.Test/MapDaprScheduledJobHandlerTest.cs index e8d4cb3e2..aec9aafff 100644 --- a/test/Dapr.Jobs.Analyzer.Test/MapDaprScheduledJobHandlerTest.cs +++ b/test/Dapr.Jobs.Analyzer.Test/MapDaprScheduledJobHandlerTest.cs @@ -26,6 +26,7 @@ public async Task AnalyzeJobSchedulerHandler_ShouldRaiseDiagnostic_WhenJobHasNoE using Dapr.Jobs.Extensions; using Dapr.Jobs.Models; + #pragma warning disable DAPR_JOBS public static class Program { public static void Main() @@ -41,10 +42,11 @@ public static void Main() Encoding.UTF8.GetBytes("This is a test"), repeats: 10).GetAwaiter().GetResult(); } } + #pragma warning restore DAPR_JOBS """; var expected = VerifyAnalyzer.Diagnostic(MapDaprScheduledJobHandlerAnalyzer.DaprJobHandlerRule) - .WithSpan(22, 25, 23, 83) + .WithSpan(23, 25, 24, 83) .WithMessage( "Job invocations require the MapDaprScheduledJobHandler be set and configured for job name 'myJob' on IEndpointRouteBuilder"); @@ -66,6 +68,7 @@ public async Task AnalyzeJobSchedulerHandler_ShouldNotRaiseDiagnostic_WhenSchedu using Dapr.Jobs.Extensions; using Dapr.Jobs.Models; + #pragma warning disable DAPR_JOBS public static class Program { public static void Main() @@ -78,6 +81,7 @@ public static void Main() var daprJobsClient = scope.ServiceProvider.GetRequiredService(); } } + #pragma warning restore DAPR_JOBS """; var analyzer = new VerifyAnalyzer(Utilities.GetReferences()); @@ -98,6 +102,7 @@ public async Task AnalyzeJobSchedulerHandler_ShouldRaiseDiagnostic_ForEachInstan using Dapr.Jobs.Extensions; using Dapr.Jobs.Models; + #pragma warning disable DAPR_JOBS public static class Program { public static void Main() @@ -115,14 +120,15 @@ public static void Main() Encoding.UTF8.GetBytes("This is a test"), repeats: 10).GetAwaiter().GetResult(); } } + #pragma warning restore DAPR_JOBS """; var expected1 = VerifyAnalyzer.Diagnostic(MapDaprScheduledJobHandlerAnalyzer.DaprJobHandlerRule) - .WithSpan(22, 25, 23, 83) + .WithSpan(23, 25, 24, 83) .WithMessage( "Job invocations require the MapDaprScheduledJobHandler be set and configured for job name 'myJob' on IEndpointRouteBuilder"); var expected2 = VerifyAnalyzer.Diagnostic(MapDaprScheduledJobHandlerAnalyzer.DaprJobHandlerRule) - .WithSpan(24, 25, 25, 83) + .WithSpan(25, 25, 26, 83) .WithMessage("Job invocations require the MapDaprScheduledJobHandler be set and configured for job name 'myJob2' on IEndpointRouteBuilder"); var analyzer = new VerifyAnalyzer(Utilities.GetReferences()); await analyzer.VerifyAnalyzerAsync(testCode, expected1, expected2); @@ -142,6 +148,7 @@ public async Task AnalyzeJobSchedulerHandler_ShouldNotRaiseDiagnostic_WhenJobHas using Dapr.Jobs.Extensions; using Dapr.Jobs.Models; + #pragma warning disable DAPR_JOBS public static class Program { public static void Main() @@ -164,6 +171,7 @@ public static void Main() }, TimeSpan.FromSeconds(5)); } } + #pragma warning restore DAPR_JOBS """; var analyzer = new VerifyAnalyzer(Utilities.GetReferences()); @@ -183,7 +191,8 @@ public async Task AnalyzeJobSchedulerHandler_ShouldNotRaiseDiagnostic_WhenJobHas using Dapr.Jobs; using Dapr.Jobs.Extensions; using Dapr.Jobs.Models; - + + #pragma warning disable DAPR_JOBS public static class Program { public static async Task Main() @@ -206,6 +215,7 @@ await daprJobsClient.ScheduleJobAsync("myJob2", DaprJobSchedule.FromDuration(Tim }, TimeSpan.FromSeconds(5)); } } + #pragma warning restore DAPR_JOBS """; var analyzer = new VerifyAnalyzer(Utilities.GetReferences()); @@ -225,7 +235,8 @@ public async Task AnalyzeJobSchedulerHandler_ShouldNotRaiseDiagnostic_WhenSchedu using Dapr.Jobs; using Dapr.Jobs.Extensions; using Dapr.Jobs.Models; - + + #pragma warning disable DAPR_JOBS public static class Program { public static async Task Main() @@ -245,6 +256,7 @@ public static Task ScheduleJobAsync(string jobNAme) return Task.CompletedTask; } } + #pragma warning restore DAPR_JOBS """; diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 39b6b97e5..65b969f3b 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -8,6 +8,7 @@ $(RepoRoot)bin\$(Configuration)\test\$(MSBuildProjectName)\ false + $(NoWarn);DAPR_CONVERSATION;DAPR_JOBS;DAPR_DISTRIBUTEDLOCK;DAPR_CRYPTOGRAPHY