diff --git a/src/Ydb.Sdk/CHANGELOG.md b/src/Ydb.Sdk/CHANGELOG.md index f59e6b6b..24ae80ae 100644 --- a/src/Ydb.Sdk/CHANGELOG.md +++ b/src/Ydb.Sdk/CHANGELOG.md @@ -1,3 +1,4 @@ +- Added XML documentation for all public APIs in `Ydb.Sdk`. - Feat ADO.NET: Added dispose timeout (10 seconds) to `PoolingSessionSource`. - Feat ADO.NET: Added `EnableImplicitSession` to support implicit sessions. diff --git a/src/Ydb.Sdk/src/Ado/BulkUpsert/BulkUpsertImporter.cs b/src/Ydb.Sdk/src/Ado/BulkUpsert/BulkUpsertImporter.cs index dc563257..38907eaa 100644 --- a/src/Ydb.Sdk/src/Ado/BulkUpsert/BulkUpsertImporter.cs +++ b/src/Ydb.Sdk/src/Ado/BulkUpsert/BulkUpsertImporter.cs @@ -6,7 +6,7 @@ namespace Ydb.Sdk.Ado.BulkUpsert; -public sealed class BulkUpsertImporter : IBulkUpsertImporter +internal class BulkUpsertImporter : IBulkUpsertImporter { private readonly IDriver _driver; private readonly string _tablePath; diff --git a/src/Ydb.Sdk/src/Ado/RetryPolicy/IRetryPolicy.cs b/src/Ydb.Sdk/src/Ado/RetryPolicy/IRetryPolicy.cs index 84d977ef..680b75ca 100644 --- a/src/Ydb.Sdk/src/Ado/RetryPolicy/IRetryPolicy.cs +++ b/src/Ydb.Sdk/src/Ado/RetryPolicy/IRetryPolicy.cs @@ -1,6 +1,27 @@ namespace Ydb.Sdk.Ado.RetryPolicy; +/// +/// Defines the contract for retry policies used by YDB operations. +/// +/// +/// IRetryPolicy provides a way to implement custom retry logic for YDB operations. +/// The recommended implementation is , but custom implementations +/// can be created for specific use cases. When implementing a custom retry policy, ensure +/// you understand the implications of retrying operations and handle idempotency correctly. +/// public interface IRetryPolicy { + /// + /// Calculates the delay before the next retry attempt. + /// + /// The that was thrown during the last execution attempt. + /// The current attempt number (0-based). + /// + /// The delay before the next retry attempt, or null if no more retries should be attempted. + /// + /// + /// This method is called for each retry attempt. Return null to stop retrying. + /// Consider the , attempt number, and operation idempotency when making retry decisions. + /// public TimeSpan? GetNextDelay(YdbException ydbException, int attempt); } diff --git a/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicy.cs b/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicy.cs index ae4a641d..728ce873 100644 --- a/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicy.cs +++ b/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicy.cs @@ -3,10 +3,23 @@ namespace Ydb.Sdk.Ado.RetryPolicy; /// -/// See AWS paper +/// Default retry policy implementation for YDB operations using exponential backoff with jitter. /// +/// +/// YdbRetryPolicy implements the recommended retry strategy for YDB operations based on +/// AWS best practices. +/// It uses different backoff strategies for different types of errors and includes jitter +/// to prevent thundering herd problems. This is the recommended implementation of . +/// public class YdbRetryPolicy : IRetryPolicy { + /// + /// Gets the default retry policy instance with default configuration. + /// + /// + /// This instance uses the default configuration from . + /// It's suitable for most use cases and provides a good balance between retry frequency and performance. + /// public static readonly YdbRetryPolicy Default = new(YdbRetryPolicyConfig.Default); private readonly int _maxAttempt; @@ -19,6 +32,14 @@ public class YdbRetryPolicy : IRetryPolicy private readonly bool _enableRetryIdempotence; private readonly IRandom _random; + /// + /// Initializes a new instance of the class with the specified configuration. + /// + /// The retry policy configuration. + /// + /// This constructor creates a retry policy with the specified configuration. + /// The policy will use different backoff strategies based on the error type and attempt number. + /// public YdbRetryPolicy(YdbRetryPolicyConfig config) { _maxAttempt = config.MaxAttempts; @@ -32,11 +53,31 @@ public YdbRetryPolicy(YdbRetryPolicyConfig config) _random = ThreadLocalRandom.Instance; } + /// + /// Initializes a new instance of the class with the specified configuration and random number generator. + /// + /// The retry policy configuration. + /// The random number generator for jitter calculations. + /// + /// This constructor is used for testing purposes to provide deterministic behavior. + /// In production code, use the constructor that takes only the configuration parameter. + /// internal YdbRetryPolicy(YdbRetryPolicyConfig config, IRandom random) : this(config) { _random = random; } + /// + /// + /// This method implements different retry strategies based on the YDB status code: + /// - BadSession/SessionBusy: Immediate retry (TimeSpan.Zero) + /// - Aborted/Undetermined: Fast backoff with full jitter + /// - Unavailable/Transport errors: Fast backoff with equal jitter + /// - Overloaded/Resource exhausted: Slow backoff with equal jitter + /// - Other errors: No retry (null) + /// + /// The policy respects the maximum attempt limit and idempotence settings. + /// public TimeSpan? GetNextDelay(YdbException ydbException, int attempt) { if (attempt >= _maxAttempt - 1 || (!_enableRetryIdempotence && !ydbException.IsTransient)) diff --git a/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyConfig.cs b/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyConfig.cs index 017c3d2c..fe8f0f98 100644 --- a/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyConfig.cs +++ b/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyConfig.cs @@ -1,21 +1,97 @@ namespace Ydb.Sdk.Ado.RetryPolicy; +/// +/// Configuration settings for the . +/// +/// +/// YdbRetryPolicyConfig provides configuration options for customizing the retry behavior +/// of YDB operations. The default values are suitable for most use cases, but can be +/// adjusted based on specific requirements and performance characteristics. +/// public class YdbRetryPolicyConfig { + /// + /// Gets the default retry policy configuration. + /// + /// + /// This configuration provides a good balance between retry frequency and performance + /// for most YDB operations. It can be used as a starting point for custom configurations. + /// public static readonly YdbRetryPolicyConfig Default = new(); + /// + /// Gets or sets the maximum number of retry attempts. + /// + /// + /// The total number of attempts will be MaxAttempts (including the initial attempt). + /// Setting this to 1 disables retries entirely. + /// Default value: 10. + /// public int MaxAttempts { get; init; } = 10; + /// + /// Gets or sets the base delay in milliseconds for fast backoff strategies. + /// + /// + /// This is used for errors that typically resolve quickly, such as temporary + /// unavailability or TLI (Transaction Lock Invalidated). + /// The actual delay will be calculated using exponential backoff with jitter. + /// Default value: 5 ms. + /// public int FastBackoffBaseMs { get; init; } = 5; + /// + /// Gets or sets the base delay in milliseconds for slow backoff strategies. + /// + /// + /// This is used for errors that may take longer to resolve, such as overload + /// or resource exhaustion. The actual delay will be calculated using + /// exponential backoff with jitter. + /// Default value: 50 ms. + /// public int SlowBackoffBaseMs { get; init; } = 50; + /// + /// Gets or sets the maximum delay in milliseconds for fast backoff strategies. + /// + /// + /// This caps the maximum delay for fast backoff to prevent excessively long waits. + /// The exponential backoff will not exceed this value. + /// Default value: 500 ms. + /// public int FastCapBackoffMs { get; init; } = 500; + /// + /// Gets or sets the maximum delay in milliseconds for slow backoff strategies. + /// + /// + /// This caps the maximum delay for slow backoff to prevent excessively long waits. + /// The exponential backoff will not exceed this value. + /// Default value: 5000 ms. + /// public int SlowCapBackoffMs { get; init; } = 5_000; + /// + /// Gets or sets a value indicating whether to enable retry for idempotent statuses. + /// + /// + /// When false, only transient errors are retried. When true, all retryable statuses + /// are retried, which means the operation may be executed twice. This happens because + /// some statuses (like unavailable) don't indicate whether the server processed the + /// operation - the connection might have been lost during the response. Enable this + /// only if you are certain that the operations being retried are idempotent. + /// Default value: false. + /// public bool EnableRetryIdempotence { get; init; } = false; + /// + /// Returns a string representation of the retry policy configuration. + /// + /// A string containing all configuration values in a readable format. + /// + /// This method is useful for logging and debugging purposes to see the current + /// retry policy configuration values. + /// public override string ToString() => $"MaxAttempt={MaxAttempts};" + $"FastBackoffBaseMs={FastBackoffBaseMs};" + $"SlowBackoffBaseMs={SlowBackoffBaseMs};" + diff --git a/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyExecutor.cs b/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyExecutor.cs index 59d61589..969e25e2 100644 --- a/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyExecutor.cs +++ b/src/Ydb.Sdk/src/Ado/RetryPolicy/YdbRetryPolicyExecutor.cs @@ -10,20 +10,20 @@ public YdbRetryPolicyExecutor(IRetryPolicy retryPolicy) } /// - /// Executes the specified asynchronous operation and returns the result. + /// Executes the specified asynchronous operation and returns the result. /// /// - /// A function that returns a started task of type . + /// A function that returns a started task of type . /// /// - /// A cancellation token used to cancel the retry operation, but not operations that are already in flight - /// or that already completed successfully. + /// A cancellation token used to cancel the retry operation, but not operations that are already in flight + /// or that already completed successfully. /// /// The result type of the returned by . /// - /// A task that will run to completion if the original task completes successfully (either the - /// first time or after retrying transient failures). If the task fails with a non-transient error or - /// the retry limit is reached, the returned task will become faulted and the exception must be observed. + /// A task that will run to completion if the original task completes successfully (either the + /// first time or after retrying transient failures). If the task fails with a non-transient error or + /// the retry limit is reached, the returned task will become faulted and the exception must be observed. /// public Task ExecuteAsync( Func> operation, diff --git a/src/Ydb.Sdk/src/Ado/Schema/YdbTableStats.cs b/src/Ydb.Sdk/src/Ado/Schema/YdbTableStats.cs index 62ebee87..e07a9b25 100644 --- a/src/Ydb.Sdk/src/Ado/Schema/YdbTableStats.cs +++ b/src/Ydb.Sdk/src/Ado/Schema/YdbTableStats.cs @@ -1,6 +1,6 @@ namespace Ydb.Sdk.Ado.Schema; -public class YdbTableStats +internal class YdbTableStats { public YdbTableStats(Table.TableStats tableStats) { diff --git a/src/Ydb.Sdk/src/Ado/Transaction/TransactionMode.cs b/src/Ydb.Sdk/src/Ado/Transaction/TransactionMode.cs index ce516256..9e050244 100644 --- a/src/Ydb.Sdk/src/Ado/Transaction/TransactionMode.cs +++ b/src/Ydb.Sdk/src/Ado/Transaction/TransactionMode.cs @@ -2,12 +2,74 @@ namespace Ydb.Sdk.Ado; +/// +/// Specifies the transaction isolation mode for YDB operations. +/// +/// +/// TransactionMode defines the isolation level and consistency guarantees +/// for database operations within a transaction. +/// +/// +/// For more information about YDB transaction modes, see: +/// YDB Transactions Documentation. +/// +/// public enum TransactionMode { + /// + /// Serializable read-write transaction mode. + /// + /// + /// Provides the strictest isolation level for custom transactions. + /// Guarantees that the result of successful parallel transactions is equivalent + /// to their serial execution, with no read anomalies for successful transactions. + /// This is the default mode for read-write operations. + /// SerializableRw, + + /// + /// Snapshot read-only transaction mode. + /// + /// + /// All read operations within the transaction access the database snapshot. + /// All data reads are consistent. The snapshot is taken when the transaction begins, + /// meaning the transaction sees all changes committed before it began. + /// Only read operations are allowed. + /// SnapshotRo, + + /// + /// Stale read-only transaction mode. + /// + /// + /// Read operations within the transaction may return results that are slightly + /// out-of-date (lagging by fractions of a second). Each individual read returns + /// consistent data, but no consistency between different reads is guaranteed. + /// Only read operations are allowed. + /// StaleRo, + /// + /// Online read-only transaction mode. + /// + /// + /// Each read operation in the transaction reads the data that is most recent + /// at execution time. Each individual read operation returns consistent data, + /// but no consistency is guaranteed between reads. Reading the same table range + /// twice may return different results. + /// Only read operations are allowed. + /// OnlineRo, + + /// + /// Online inconsistent read-only transaction mode. + /// + /// + /// Each read operation in the transaction reads the data that is most recent + /// at execution time. Even the data fetched by a particular read operation may + /// contain inconsistent results. This mode provides the highest performance + /// but the lowest consistency guarantees. + /// Only read operations are allowed. + /// OnlineInconsistentRo } diff --git a/src/Ydb.Sdk/src/Ado/YdbCommand.cs b/src/Ydb.Sdk/src/Ado/YdbCommand.cs index c8618a54..7df69229 100644 --- a/src/Ydb.Sdk/src/Ado/YdbCommand.cs +++ b/src/Ydb.Sdk/src/Ado/YdbCommand.cs @@ -6,6 +6,13 @@ namespace Ydb.Sdk.Ado; +/// +/// Represents a SQL command to execute against a YDB database. This class cannot be inherited. +/// +/// +/// YdbCommand provides a standard ADO.NET command interface for executing SQL statements +/// against YDB databases. It supports both synchronous and asynchronous execution methods. +/// public sealed class YdbCommand : DbCommand { private YdbConnection? _ydbConnection; @@ -14,15 +21,34 @@ public sealed class YdbCommand : DbCommand private YdbConnection YdbConnection => _ydbConnection ?? throw new InvalidOperationException("Connection property has not been initialized"); + /// + /// Initializes a new instance of the class. + /// public YdbCommand() { } + /// + /// Initializes a new instance of the class with the specified connection. + /// + /// A that represents the connection to a YDB server. public YdbCommand(YdbConnection ydbConnection) { _ydbConnection = ydbConnection; } + /// + /// Initializes a new instance of the class with the text of the query, a + /// , and the . + /// + /// The text of the query. + /// A that represents the connection to a YDB server. + public YdbCommand(string commandText, YdbConnection? ydbConnection = null) + { + _commandText = commandText; + _ydbConnection = ydbConnection; + } + public override void Cancel() { } diff --git a/src/Ydb.Sdk/src/Ado/YdbConnection.cs b/src/Ydb.Sdk/src/Ado/YdbConnection.cs index efd44cad..972c626d 100644 --- a/src/Ydb.Sdk/src/Ado/YdbConnection.cs +++ b/src/Ydb.Sdk/src/Ado/YdbConnection.cs @@ -8,6 +8,13 @@ namespace Ydb.Sdk.Ado; +/// +/// Represents a connection to a YDB database. +/// +/// +/// YdbConnection provides a standard ADO.NET connection interface for YDB databases. +/// It manages database sessions and provides access to YDB-specific functionality. +/// public sealed class YdbConnection : DbConnection { private static readonly StateChangeEventArgs ClosedToOpenEventArgs = @@ -39,15 +46,28 @@ internal ISession Session private ISession _session = null!; + /// + /// Initializes a new instance of the class. + /// public YdbConnection() { } + /// + /// Initializes a new instance of the class with the specified connection string. + /// + /// The connection string used to establish the connection. public YdbConnection(string connectionString) { ConnectionStringBuilder = new YdbConnectionStringBuilder(connectionString); } + /// + /// Initializes a new instance of the class with the specified connection string builder. + /// + /// + /// The used to establish the connection. + /// public YdbConnection(YdbConnectionStringBuilder connectionStringBuilder) { ConnectionStringBuilder = connectionStringBuilder; diff --git a/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs b/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs index 79ef36e7..3f3f081c 100644 --- a/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs +++ b/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs @@ -8,13 +8,36 @@ namespace Ydb.Sdk.Ado; +/// +/// Provides a simple way to create and manage the contents of connection strings used by +/// the class. +/// +/// +/// YdbConnectionStringBuilder provides strongly-typed properties for building YDB connection strings. +/// It supports all standard ADO.NET connection string parameters plus YDB-specific options. +/// +/// +/// For more information about YDB, see: +/// YDB Documentation. +/// +/// public sealed class YdbConnectionStringBuilder : DbConnectionStringBuilder { + /// + /// Initializes a new instance of the class. + /// public YdbConnectionStringBuilder() { InitDefaultValues(); } + /// + /// Initializes a new instance of the class + /// with the specified connection string. + /// + /// + /// The connection string to parse and use as the basis for the internal connection string. + /// public YdbConnectionStringBuilder(string connectionString) { InitDefaultValues(); @@ -43,6 +66,13 @@ private void InitDefaultValues() _enableImplicitSession = false; } + /// + /// Gets or sets the host name or IP address of the YDB server. + /// + /// + /// Specifies the hostname or IP address where the YDB server is running. + /// Default value: localhost. + /// public string Host { get => _host; @@ -55,6 +85,14 @@ public string Host private string _host = null!; + /// + /// Gets or sets the port number of the YDB server. + /// + /// + /// Specifies the port number where the YDB server is listening. + /// Must be between 1 and 65535. + /// Default value: 2136. + /// public int Port { get => _port; @@ -72,6 +110,13 @@ public int Port private int _port; + /// + /// Gets or sets the database path. + /// + /// + /// Specifies the path to the YDB database to connect to. + /// Default value: /local. + /// public string Database { get => _database; @@ -84,6 +129,14 @@ public string Database private string _database = null!; + /// + /// Gets or sets the username for authentication. + /// + /// + /// Specifies the username used for authenticating with the YDB server. + /// If not specified, authentication using a username and password is disabled. + /// Default value: null. + /// public string? User { get => _user; @@ -96,6 +149,14 @@ public string? User private string? _user; + /// + /// Gets or sets the password for authentication. + /// + /// + /// Specifies the password used for authentication with the YDB server. + /// If not specified, a password is not used. + /// Default value: null. + /// public string? Password { get => _password; @@ -108,6 +169,14 @@ public string? Password private string? _password; + /// + /// Gets or sets the maximum number of sessions in the pool. + /// + /// + /// Specifies the maximum number of sessions that can be created and maintained + /// in the session pool. Must be greater than 0. + /// Default value: 100. + /// public int MaxSessionPool { get => _maxSessionPool; @@ -125,6 +194,14 @@ public int MaxSessionPool private int _maxSessionPool; + /// + /// Gets or sets the minimum number of sessions in the pool. + /// + /// + /// Specifies the minimum number of sessions to maintain in the session pool. + /// Must be greater than or equal to 0. + /// Default value: 0. + /// public int MinSessionPool { get => _minSessionPool; @@ -142,6 +219,14 @@ public int MinSessionPool private int _minSessionPool; + /// + /// Gets or sets the session idle timeout in seconds. + /// + /// + /// Specifies how long a session can remain idle before being closed. + /// Must be greater than or equal to 0. + /// Default value: 300 seconds (5 minutes). + /// public int SessionIdleTimeout { get => _sessionIdleTimeout; @@ -159,6 +244,14 @@ public int SessionIdleTimeout private int _sessionIdleTimeout; + /// + /// Gets or sets a value indicating whether to use TLS encryption. + /// + /// + /// When true, the connection uses TLS encryption (grpcs://). + /// When false, the connection uses plain text (grpc://). + /// Default value: false. + /// public bool UseTls { get => _useTls; @@ -171,6 +264,14 @@ public bool UseTls private bool _useTls; + /// + /// Gets or sets the path to the root certificate file. + /// + /// + /// Specifies the path to a PEM-encoded root certificate file for TLS verification. + /// Setting this property automatically enables TLS (UseTls = true). + /// Default value: null. + /// public string? RootCertificate { get => _rootCertificate; @@ -185,6 +286,14 @@ public string? RootCertificate private string? _rootCertificate; + /// + /// Gets or sets the connection timeout in seconds. + /// + /// + /// Specifies the maximum time to wait when establishing a connection to the server. + /// Must be greater than or equal to 0. Set to 0 for infinite timeout. + /// Default value: 10 seconds. + /// public int ConnectTimeout { get => _connectTimeout; @@ -202,6 +311,14 @@ public int ConnectTimeout private int _connectTimeout; + /// + /// Gets or sets the keep-alive ping delay in seconds. + /// + /// + /// Specifies the interval between keep-alive ping messages to detect broken connections. + /// Must be greater than or equal to 0. Set to 0 to disable keep-alive pings. + /// Default value: 10 seconds. + /// public int KeepAlivePingDelay { get => _keepAlivePingDelay; @@ -219,6 +336,15 @@ public int KeepAlivePingDelay private int _keepAlivePingDelay; + /// + /// Gets or sets the keep-alive ping timeout in seconds. + /// + /// + /// Specifies the maximum time to wait for a keep-alive ping response before + /// considering the connection broken. Must be greater than or equal to 0. + /// Set to 0 for infinite timeout. + /// Default value: 5 seconds. + /// public int KeepAlivePingTimeout { get => _keepAlivePingTimeout; @@ -237,6 +363,16 @@ public int KeepAlivePingTimeout private int _keepAlivePingTimeout; + /// + /// Gets or sets a value indicating whether to enable multiple HTTP/2 connections. + /// + /// + /// When true, enables automatic scaling of HTTP/2 connections within a single gRPC channel + /// to one node of the cluster. This is rarely needed but can improve performance for + /// high-load scenarios with a single node. + /// When false, uses a single HTTP/2 connection per node. + /// Default value: false. + /// public bool EnableMultipleHttp2Connections { get => _enableMultipleHttp2Connections; @@ -249,6 +385,15 @@ public bool EnableMultipleHttp2Connections private bool _enableMultipleHttp2Connections; + /// + /// Gets or sets the maximum size for outgoing messages in bytes. + /// + /// + /// Specifies the maximum size of messages that can be sent to the server. + /// Note: server-side limit is 64 MB. Exceeding this limit may result in + /// "resource exhausted" errors or unpredictable behavior. + /// Default value: 4194304 bytes (4 MB). + /// public int MaxSendMessageSize { get => _maxSendMessageSize; @@ -261,6 +406,13 @@ public int MaxSendMessageSize private int _maxSendMessageSize; + /// + /// Gets or sets the maximum size for incoming messages in bytes. + /// + /// + /// Specifies the maximum size of messages that can be received from the server. + /// Default value: 4194304 bytes (4 MB). + /// public int MaxReceiveMessageSize { get => _maxReceiveMessageSize; @@ -273,6 +425,14 @@ public int MaxReceiveMessageSize private int _maxReceiveMessageSize; + /// + /// Gets or sets a value indicating whether to disable server load balancing. + /// + /// + /// When true, disables server load balancing and uses direct connections. + /// When false, enables server load balancing for better performance. + /// Default value: false. + /// public bool DisableServerBalancer { get => _disableServerBalancer; @@ -285,6 +445,14 @@ public bool DisableServerBalancer private bool _disableServerBalancer; + /// + /// Gets or sets a value indicating whether to disable service discovery. + /// + /// + /// When true, disables automatic service discovery and uses direct gRPC connections. + /// When false, enables service discovery for automatic endpoint resolution. + /// Default value: false. + /// public bool DisableDiscovery { get => _disableDiscovery; @@ -297,6 +465,14 @@ public bool DisableDiscovery private bool _disableDiscovery; + /// + /// Gets or sets the session creation timeout in seconds. + /// + /// + /// Specifies the maximum time to wait when creating a new session. + /// Must be greater than or equal to 0. Set to 0 for infinite timeout. + /// Default value: 5 seconds. + /// public int CreateSessionTimeout { get => _createSessionTimeout; @@ -315,6 +491,17 @@ public int CreateSessionTimeout private int _createSessionTimeout; + /// + /// Gets or sets a value indicating whether to enable implicit session management. + /// + /// + /// When true, implicit session management is enabled: the server creates and destroys + /// sessions automatically for each operation. In this mode, the Session Pool is not created, + /// and sessions are not stored on the client side. Interactive client transactions are + /// not supported in this mode. + /// When false, the standard YDB sessions for tables (YDB has topics, coordination service, etc.) are used. + /// Default value: false. + /// public bool EnableImplicitSession { get => _enableImplicitSession; @@ -327,10 +514,33 @@ public bool EnableImplicitSession private bool _enableImplicitSession; + /// + /// Gets or sets the logger factory for logging operations. + /// + /// + /// Specifies the logger factory used for creating loggers throughout the SDK. + /// Default value: NullLoggerFactory.Instance (no logging). + /// public ILoggerFactory LoggerFactory { get; init; } = NullLoggerFactory.Instance; + /// + /// Gets or sets the credentials provider for authentication. + /// + /// + /// Specifies the credentials provider used for authenticating with the YDB server. + /// If not provided, authentication is not used. + /// Default value: null. + /// public ICredentialsProvider? CredentialsProvider { get; init; } + /// + /// Gets or sets the collection of server certificates for TLS verification. + /// + /// + /// Specifies additional server certificates to trust for TLS verification. + /// If not provided, the system certificate store is used. + /// Default value: null. + /// public X509Certificate2Collection? ServerCertificates { get; init; } private void SaveValue(string propertyName, object? value) diff --git a/src/Ydb.Sdk/src/Ado/YdbDataReader.cs b/src/Ydb.Sdk/src/Ado/YdbDataReader.cs index 3077ad34..ae8aaa54 100644 --- a/src/Ydb.Sdk/src/Ado/YdbDataReader.cs +++ b/src/Ydb.Sdk/src/Ado/YdbDataReader.cs @@ -6,6 +6,14 @@ namespace Ydb.Sdk.Ado; +/// +/// Provides a way of reading a forward-only stream of data rows from a YDB database. This class cannot be inherited. +/// +/// +/// YdbDataReader provides a means of reading a forward-only stream of data rows from a YDB database. +/// It implements both synchronous and asynchronous data access methods, and supports streaming of large result sets. +/// The reader is optimized for YDB-specific data types and provides access to YDB-specific functionality. +/// // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault public sealed class YdbDataReader : DbDataReader, IAsyncEnumerable { @@ -63,6 +71,14 @@ private YdbDataReader( _ydbTransaction = ydbTransaction; } + /// + /// Creates a new instance of YdbDataReader from a result set stream. + /// + /// The server stream containing query results. + /// Callback for handling non-success status codes. + /// Optional transaction context. + /// Cancellation token for the operation. + /// A task that represents the asynchronous operation. The task result contains the initialized YdbDataReader. internal static async Task CreateYdbDataReader( IServerStream resultSetStream, Action onNotSuccessStatusCode, @@ -86,18 +102,48 @@ private async Task Init(CancellationToken cancellationToken) ReaderState = State.ReadResultSet; } + /// + /// Gets the value of the specified column as a Boolean. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override bool GetBoolean(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Bool, ordinal).GetBool(); + /// + /// Gets the value of the specified column as a byte. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override byte GetByte(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Uint8, ordinal).GetUint8(); + /// + /// Gets the value of the specified column as a signed byte. + /// + /// The zero-based column ordinal. + /// The value of the specified column as a signed byte. public sbyte GetSByte(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Int8, ordinal).GetInt8(); + /// + /// Gets the value of the specified column as a byte array. + /// + /// The zero-based column ordinal. + /// The value of the specified column as a byte array. public byte[] GetBytes(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.String, ordinal).GetBytes(); public byte[] GetYson(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Yson, ordinal).GetYson(); + /// + /// Reads a stream of bytes from the specified column offset into the buffer as an array. + /// + /// The zero-based column ordinal. + /// The index within the field from which to start the read operation. + /// The buffer into which to read the stream of bytes. + /// The index for buffer to start the read operation. + /// The maximum length to copy into the buffer. + /// The actual number of bytes read. + /// Thrown when dataOffset, bufferOffset, or length are out of range. public override long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length) { var bytes = GetBytes(ordinal); @@ -121,6 +167,14 @@ public override long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int return copyCount; } + /// + /// Gets the value of the specified column as a single character. + /// + /// The zero-based column ordinal. + /// The value of the specified column as a character. + /// + /// Thrown when the string is empty or cannot be converted to a character. + /// public override char GetChar(int ordinal) { var str = GetString(ordinal); @@ -128,6 +182,16 @@ public override char GetChar(int ordinal) return str.Length == 0 ? throw new InvalidCastException("Could not read char - string was empty") : str[0]; } + /// + /// Reads a stream of characters from the specified column offset into the buffer as an array. + /// + /// The zero-based column ordinal. + /// The index within the field from which to start the read operation. + /// The buffer into which to read the stream of characters. + /// The index for buffer to start the read operation. + /// The maximum length to copy into the buffer. + /// The actual number of characters read. + /// Thrown when dataOffset, bufferOffset, or length are out of range. public override long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length) { var chars = GetString(ordinal).ToCharArray(); @@ -174,8 +238,18 @@ private static void CheckOffsets(long dataOffset, T[]? buffer, int bufferOffs } } + /// + /// Gets the name of the data type of the specified column. + /// + /// The zero-based column ordinal. + /// The string representing the data type of the specified column. public override string GetDataTypeName(int ordinal) => ReaderMetadata.GetColumn(ordinal).Type.YqlTableType(); + /// + /// Gets the value of the specified column as a DateTime object. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override DateTime GetDateTime(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -192,6 +266,11 @@ public override DateTime GetDateTime(int ordinal) }; } + /// + /// Gets the value of the specified column as a TimeSpan object. + /// + /// The zero-based column ordinal. + /// The value of the specified column as a TimeSpan. public TimeSpan GetInterval(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -204,6 +283,11 @@ public TimeSpan GetInterval(int ordinal) }; } + /// + /// Gets the value of the specified column as a Decimal object. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override decimal GetDecimal(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -213,6 +297,11 @@ public override decimal GetDecimal(int ordinal) : throw InvalidCastException(Type.TypeOneofCase.DecimalType, ordinal); } + /// + /// Gets the value of the specified column as a double-precision floating point number. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override double GetDouble(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -225,6 +314,12 @@ public override double GetDouble(int ordinal) }; } + /// + /// Gets the value of the specified column as the requested type. + /// + /// The type of the value to return. + /// The zero-based column ordinal. + /// The value of the specified column. public override T GetFieldValue(int ordinal) { if (typeof(T) == typeof(TextReader)) @@ -245,6 +340,11 @@ public override T GetFieldValue(int ordinal) return base.GetFieldValue(ordinal); } + /// + /// Gets the Type that is the data type of the object. + /// + /// The zero-based column ordinal. + /// The Type that is the data type of the object. public override System.Type GetFieldType(int ordinal) { var type = ReaderMetadata.GetColumn(ordinal).Type; @@ -289,11 +389,26 @@ or Type.Types.PrimitiveTypeId.JsonDocument }; } + /// + /// Gets the value of the specified column as a single-precision floating point number. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override float GetFloat(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Float, ordinal).GetFloat(); + /// + /// Gets the value of the specified column as a globally unique identifier (GUID). + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override Guid GetGuid(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Uuid, ordinal).GetUuid(); + /// + /// Gets the value of the specified column as a 16-bit signed integer. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override short GetInt16(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -307,6 +422,11 @@ public override short GetInt16(int ordinal) }; } + /// + /// Gets the value of the specified column as a 16-bit unsigned integer. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public ushort GetUint16(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -319,6 +439,11 @@ public ushort GetUint16(int ordinal) }; } + /// + /// Gets the value of the specified column as a 32-bit signed integer. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override int GetInt32(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -334,6 +459,11 @@ public override int GetInt32(int ordinal) }; } + /// + /// Gets the value of the specified column as a 32-bit unsigned integer. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public uint GetUint32(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -347,6 +477,11 @@ public uint GetUint32(int ordinal) }; } + /// + /// Gets the value of the specified column as a 64-bit signed integer. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override long GetInt64(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -364,6 +499,11 @@ public override long GetInt64(int ordinal) }; } + /// + /// Gets the value of the specified column as a 64-bit unsigned integer. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public ulong GetUint64(int ordinal) { var type = UnwrapColumnType(ordinal); @@ -378,8 +518,19 @@ public ulong GetUint64(int ordinal) }; } + /// + /// Gets the name of the specified column. + /// + /// The zero-based column ordinal. + /// The name of the specified column. public override string GetName(int ordinal) => ReaderMetadata.GetColumn(ordinal).Name; + /// + /// Gets the column ordinal given the name of the column. + /// + /// The name of the column. + /// The zero-based column ordinal. + /// Thrown when the column name is not found. public override int GetOrdinal(string name) { if (ReaderMetadata.ColumnNameToOrdinal.TryGetValue(name, out var ordinal)) @@ -390,16 +541,41 @@ public override int GetOrdinal(string name) throw new IndexOutOfRangeException($"Field not found in row: {name}"); } + /// + /// Gets the value of the specified column as a string. + /// + /// The zero-based column ordinal. + /// The value of the specified column. public override string GetString(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Utf8, ordinal).GetText(); + /// + /// Gets the value of the specified column as a TextReader. + /// + /// The zero-based column ordinal. + /// A TextReader containing the column value. public override TextReader GetTextReader(int ordinal) => new StringReader(GetString(ordinal)); + /// + /// Gets the value of the specified column as a JSON string. + /// + /// The zero-based column ordinal. + /// The value of the specified column as JSON. public string GetJson(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.Json, ordinal).GetJson(); + /// + /// Gets the value of the specified column as a JSON document string. + /// + /// The zero-based column ordinal. + /// The value of the specified column as a JSON document. public string GetJsonDocument(int ordinal) => GetPrimitiveValue(Type.Types.PrimitiveTypeId.JsonDocument, ordinal).GetJsonDocument(); + /// + /// Gets the value of the specified column in its native format. + /// + /// The zero-based column ordinal. + /// The value of the specified column in its native format. public override object GetValue(int ordinal) { var type = GetColumnType(ordinal); @@ -450,6 +626,11 @@ public override object GetValue(int ordinal) }; } + /// + /// Populates an array of objects with the column values of the current row. + /// + /// An array of Object into which to copy the attribute columns. + /// The number of instances of Object in the array. public override int GetValues(object[] values) { ArgumentNullException.ThrowIfNull(values); @@ -464,19 +645,65 @@ public override int GetValues(object[] values) return count; } + /// + /// Gets a value that indicates whether the specified column contains null values. + /// + /// The zero-based column ordinal. + /// true if the specified column is equivalent to DBNull; otherwise, false. public override bool IsDBNull(int ordinal) => CurrentRow[ordinal].IsNull(); + /// + /// Gets the number of columns in the current row. + /// public override int FieldCount => ReaderMetadata.FieldCount; + + /// + /// Gets the value of the specified column in its native format given the column ordinal. + /// + /// The zero-based column ordinal. + /// The value of the specified column in its native format. public override object this[int ordinal] => GetValue(ordinal); + + /// + /// Gets the value of the specified column in its native format given the column name. + /// + /// The name of the column. + /// The value of the specified column in its native format. public override object this[string name] => GetValue(GetOrdinal(name)); + + /// + /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + /// + /// For YDB, this always returns -1 as the number of affected records is not available. public override int RecordsAffected => -1; + + /// + /// Gets a value that indicates whether the data reader contains one or more rows. + /// public override bool HasRows => ReaderMetadata.RowsCount > 0; + + /// + /// Gets a value that indicates whether the data reader is closed. + /// public override bool IsClosed => ReaderState == State.Close; + /// + /// Advances the data reader to the next result set. + /// + /// true if there are more result sets; otherwise, false. public override bool NextResult() => NextResultAsync().GetAwaiter().GetResult(); + /// + /// Advances the data reader to the next record. + /// + /// true if there are more rows; otherwise, false. public override bool Read() => ReadAsync().GetAwaiter().GetResult(); + /// + /// Asynchronously advances the data reader to the next result set. + /// + /// The cancellation token. + /// A task that represents the asynchronous operation. The task result indicates whether there are more result sets. public override async Task NextResultAsync(CancellationToken cancellationToken) { ThrowIfClosed(); @@ -501,6 +728,11 @@ public override async Task NextResultAsync(CancellationToken cancellationT return ReaderState != State.IsConsumed; } + /// + /// Asynchronously advances the data reader to the next record. + /// + /// The cancellation token. + /// A task that represents the asynchronous operation. The task result indicates whether there are more rows. public override async Task ReadAsync(CancellationToken cancellationToken) { ThrowIfClosed(); @@ -534,8 +766,22 @@ private void ThrowIfClosed() } } + /// + /// Gets a value indicating the depth of nesting for the current row. + /// + /// + /// For YdbDataReader, this always returns 0 as YDB does not support nested result sets. + /// public override int Depth => 0; + /// + /// Returns an enumerator that iterates through the . + /// + /// An enumerator that can be used to iterate through the collection. + /// + /// This method provides synchronous enumeration over the data reader records. + /// Each iteration advances the reader to the next row. + /// public override IEnumerator GetEnumerator() { while (Read()) @@ -544,6 +790,21 @@ public override IEnumerator GetEnumerator() } } + /// + /// Asynchronously closes the object. + /// + /// A task representing the asynchronous operation. + /// + /// This method closes the reader and releases any resources associated with it. + /// If the reader is closed during a transaction, the transaction will be marked as failed. + /// + /// + /// Important: If the stream is not fully read to the end, the session associated with this stream + /// and the corresponding will be marked as invalid to avoid + /// errors. Because the session may be returned to the pool + /// and immediately reused for a new request while the previous one is still not completed. + /// + /// public override async Task CloseAsync() { if (ReaderState == State.Close) @@ -571,6 +832,20 @@ public override async Task CloseAsync() } } + /// + /// Closes the object. + /// + /// + /// This method closes the reader and releases any resources associated with it. + /// If the reader is closed during a transaction, the transaction will be marked as failed. + /// + /// + /// Important: If the stream is not fully read to the end, the session associated with this stream + /// and the corresponding will be marked as invalid to avoid + /// errors. Because the session may be returned to the pool + /// and immediately reused for a new request while the previous one is still not completed. + /// + /// public override void Close() => CloseAsync().GetAwaiter().GetResult(); private Type UnwrapColumnType(int ordinal) @@ -655,8 +930,31 @@ private void OnFailReadStream() } } + /// + /// Asynchronously releases the unmanaged resources used by the YdbDataReader. + /// + /// A ValueTask representing the asynchronous disposal operation. + /// + /// This method closes the reader and releases any resources associated with it. + /// + /// + /// Important: If the stream is not fully read to the end, the session associated with this stream + /// and the corresponding will be marked as invalid to avoid + /// errors. Because the session may be returned to the pool + /// and immediately reused for a new request while the previous one is still not completed. + /// + /// public override async ValueTask DisposeAsync() => await CloseAsync(); + /// + /// Returns an async enumerator that iterates through the YdbDataReader asynchronously. + /// + /// A token to cancel the enumeration. + /// An async enumerator that can be used to iterate through the YdbDataRecord collection. + /// + /// This method provides asynchronous enumeration over the data reader records. + /// Each iteration advances the reader to the next row asynchronously. + /// public async IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new()) { while (await ReadAsync(cancellationToken)) diff --git a/src/Ydb.Sdk/src/Ado/YdbDataSource.cs b/src/Ydb.Sdk/src/Ado/YdbDataSource.cs index d37e94c3..14d89304 100644 --- a/src/Ydb.Sdk/src/Ado/YdbDataSource.cs +++ b/src/Ydb.Sdk/src/Ado/YdbDataSource.cs @@ -6,6 +6,20 @@ namespace Ydb.Sdk.Ado; +/// +/// Represents a data source for YDB connections with built-in retry policy support. +/// +/// +/// YdbDataSource provides a modern, lightweight way to work with YDB databases. +/// It automatically manages connection lifecycle and provides built-in retry policy support +/// for handling transient failures. The data source can execute operations with automatic +/// retry logic and transaction management. +/// +/// +/// For more information about YDB, see: +/// YDB Documentation. +/// +/// public class YdbDataSource #if NET7_0_OR_GREATER : DbDataSource @@ -22,14 +36,34 @@ private static YdbRetryPolicyExecutor GetExecutor(YdbRetryPolicyConfig config) = private readonly YdbConnectionStringBuilder _ydbConnectionStringBuilder; private readonly YdbRetryPolicyExecutor _retryPolicyExecutor; + /// + /// Initializes a new instance of the class with default settings. + /// + /// + /// Creates a new data source with default connection string and retry policy settings. + /// public YdbDataSource() : this(new YdbDataSourceBuilder()) { } + /// + /// Initializes a new instance of the class with the specified connection string. + /// + /// The connection string to use for database connections. + /// + /// Creates a new data source with the specified connection string and default retry policy. + /// public YdbDataSource(string connectionString) : this(new YdbDataSourceBuilder(connectionString)) { } + /// + /// Initializes a new instance of the class with the specified connection string builder. + /// + /// The connection string builder to use for database connections. + /// + /// Creates a new data source with the specified connection string builder and default retry policy. + /// public YdbDataSource(YdbConnectionStringBuilder connectionStringBuilder) : this(new YdbDataSourceBuilder(connectionStringBuilder)) { @@ -66,18 +100,45 @@ YdbConnection OpenDbConnection() } } + /// + /// Creates a new . + /// + /// A new instance. + /// + /// Creates a new connection that must be opened before use. + /// The connection should be disposed when no longer needed. + /// public #if NET7_0_OR_GREATER new #endif YdbConnection CreateConnection() => CreateDbConnection(); + /// + /// Creates and opens a new . + /// + /// A new opened instance. + /// Thrown when the connection cannot be opened. + /// + /// Creates a new connection and opens it immediately. + /// The connection should be disposed when no longer needed. + /// public #if NET7_0_OR_GREATER new #endif YdbConnection OpenConnection() => OpenDbConnection(); + /// + /// Asynchronously creates and opens a new . + /// + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns an opened . + /// Thrown when the connection cannot be opened. + /// + /// Creates a new connection and opens it asynchronously. + /// The connection should be disposed when no longer needed. + /// public #if NET7_0_OR_GREATER new @@ -125,6 +186,15 @@ public async ValueTask DisposeAsync() } #endif + /// + /// Executes an operation with automatic retry policy support. + /// + /// The operation to execute with a . + /// A task representing the asynchronous operation. + /// + /// Executes the provided function with automatic retry logic for transient failures. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync(Func func) => _retryPolicyExecutor .ExecuteAsync(async cancellationToken => { @@ -132,6 +202,16 @@ public Task ExecuteAsync(Func func) => _retryPolicyExecutor await func(ydbConnection); }); + /// + /// Executes an operation with retry policy support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute with a . + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function with automatic retry logic for transient failures. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync(Func> func) => _retryPolicyExecutor .ExecuteAsync(async cancellationToken => { @@ -139,6 +219,16 @@ public Task ExecuteAsync(Func> fu return await func(ydbConnection); }); + /// + /// Executes an operation with retry policy and cancellation token support. + /// + /// The operation to execute with a and cancellation token. + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function with automatic retry logic for transient failures. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func func, CancellationToken cancellationToken = default @@ -148,6 +238,17 @@ public Task ExecuteAsync( await func(ydbConnection, ct); }, cancellationToken); + /// + /// Executes an operation with retry policy and cancellation token support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute with a and cancellation token. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function with automatic retry logic for transient failures. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func> func, CancellationToken cancellationToken = default @@ -157,6 +258,16 @@ public Task ExecuteAsync( return await func(ydbConnection, ct); }, cancellationToken); + /// + /// Executes an operation with a custom . + /// + /// The operation to execute with a . + /// The to use for this operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function with the specified . + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func func, YdbRetryPolicyConfig retryPolicyConfig @@ -166,6 +277,16 @@ YdbRetryPolicyConfig retryPolicyConfig await func(ydbConnection); }); + /// + /// Executes an operation with a custom retry policy. + /// + /// The operation to execute with a . + /// The custom retry policy to use for this operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function with the specified custom retry policy. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func func, IRetryPolicy retryPolicy @@ -175,6 +296,17 @@ IRetryPolicy retryPolicy await func(ydbConnection); }); + /// + /// Executes an operation with a custom and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute with a . + /// The to use for this operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function with the specified . + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func> func, YdbRetryPolicyConfig retryPolicyConfig @@ -184,6 +316,17 @@ YdbRetryPolicyConfig retryPolicyConfig return await func(ydbConnection); }); + /// + /// Executes an operation with a custom retry policy and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute with a . + /// The custom retry policy to use for this operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function with the specified custom retry policy. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func> func, IRetryPolicy retryPolicy @@ -193,6 +336,17 @@ IRetryPolicy retryPolicy return await func(ydbConnection); }); + /// + /// Executes an operation with a custom and cancellation token support. + /// + /// The operation to execute with a and cancellation token. + /// The to use for this operation. + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function with the specified and cancellation support. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func func, YdbRetryPolicyConfig retryPolicyConfig, @@ -203,6 +357,17 @@ public Task ExecuteAsync( await func(ydbConnection, ct); }, cancellationToken); + /// + /// Executes an operation with a custom retry policy and cancellation token support. + /// + /// The operation to execute with a and cancellation token. + /// The custom retry policy to use for this operation. + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function with the specified custom retry policy and cancellation support. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func func, IRetryPolicy retryPolicy, @@ -213,6 +378,18 @@ public Task ExecuteAsync( await func(ydbConnection, ct); }, cancellationToken); + /// + /// Executes an operation with a custom , cancellation token support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute with a and cancellation token. + /// The to use for this operation. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function with the specified and cancellation support. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func> func, YdbRetryPolicyConfig retryPolicyConfig, @@ -223,6 +400,18 @@ public Task ExecuteAsync( return await func(ydbConnection, ct); }, cancellationToken); + /// + /// Executes an operation with a custom retry policy, cancellation token support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute with a and cancellation token. + /// The custom retry policy to use for this operation. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function with the specified custom retry policy and cancellation support. + /// The connection is automatically managed and disposed after the operation. + /// public Task ExecuteAsync( Func> func, IRetryPolicy retryPolicy, @@ -233,6 +422,17 @@ public Task ExecuteAsync( return await func(ydbConnection, ct); }, cancellationToken); + /// + /// Executes an operation within a transaction with automatic retry policy support. + /// + /// The operation to execute within the transaction. + /// The transaction mode to use. Default is SerializableRw. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function within a transaction with automatic retry logic. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func func, TransactionMode transactionMode = TransactionMode.SerializableRw @@ -244,6 +444,18 @@ public Task ExecuteInTransactionAsync( await transaction.CommitAsync(cancellationToken); }); + /// + /// Executes an operation within a transaction with automatic retry policy support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute within the transaction. + /// The transaction mode to use. Default is SerializableRw. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function within a transaction with automatic retry logic. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func> func, TransactionMode transactionMode = TransactionMode.SerializableRw @@ -256,6 +468,18 @@ public Task ExecuteInTransactionAsync( return result; }); + /// + /// Executes an operation within a transaction with automatic retry policy support and cancellation token support. + /// + /// The operation to execute within the transaction with cancellation token support. + /// The transaction mode to use. Default is SerializableRw. + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function within a transaction with automatic retry logic and cancellation support. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func func, TransactionMode transactionMode = TransactionMode.SerializableRw, @@ -268,6 +492,19 @@ public Task ExecuteInTransactionAsync( await transaction.CommitAsync(ct); }, cancellationToken); + /// + /// Executes an operation within a transaction with retry policy and cancellation token support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute within the transaction with cancellation token support. + /// The transaction mode to use. Default is SerializableRw. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function within a transaction with automatic retry logic and cancellation support. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func> func, TransactionMode transactionMode = TransactionMode.SerializableRw, @@ -281,6 +518,18 @@ public Task ExecuteInTransactionAsync( return result; }, cancellationToken); + /// + /// Executes an operation within a transaction with a custom . + /// + /// The operation to execute within the transaction. + /// The to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function within a transaction with the specified . + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func func, YdbRetryPolicyConfig retryPolicyConfig, @@ -293,6 +542,19 @@ public Task ExecuteInTransactionAsync( await transaction.CommitAsync(cancellationToken); }); + /// + /// Executes an operation within a transaction with a custom and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute within the transaction. + /// The to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function within a transaction with the specified . + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func> func, YdbRetryPolicyConfig retryPolicyConfig, @@ -306,6 +568,19 @@ public Task ExecuteInTransactionAsync( return result; }); + /// + /// Executes an operation within a transaction with a custom and cancellation token support. + /// + /// The operation to execute within the transaction with cancellation token support. + /// The to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function within a transaction with the specified and cancellation support. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func func, YdbRetryPolicyConfig retryPolicyConfig, @@ -319,6 +594,20 @@ public Task ExecuteInTransactionAsync( await transaction.CommitAsync(ct); }, cancellationToken); + /// + /// Executes an operation within a transaction with a custom , cancellation token support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute within the transaction with cancellation token support. + /// The to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function within a transaction with the specified and cancellation support. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func> func, YdbRetryPolicyConfig retryPolicyConfig, @@ -333,6 +622,18 @@ public Task ExecuteInTransactionAsync( return result; }, cancellationToken); + /// + /// Executes an operation within a transaction with a custom retry policy. + /// + /// The operation to execute within the transaction. + /// The custom retry policy to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function within a transaction with the specified custom retry policy. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func func, IRetryPolicy retryPolicy, @@ -345,6 +646,19 @@ public Task ExecuteInTransactionAsync( await transaction.CommitAsync(ct); }); + /// + /// Executes an operation within a transaction with a custom retry policy and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute within the transaction. + /// The custom retry policy to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function within a transaction with the specified custom retry policy. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func> func, IRetryPolicy retryPolicy, @@ -358,6 +672,19 @@ public Task ExecuteInTransactionAsync( return result; }); + /// + /// Executes an operation within a transaction with a custom retry policy and cancellation token support. + /// + /// The operation to execute within the transaction with cancellation token support. + /// The custom retry policy to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Executes the provided function within a transaction with the specified custom retry policy and cancellation support. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func func, IRetryPolicy retryPolicy, @@ -371,6 +698,20 @@ public Task ExecuteInTransactionAsync( await transaction.CommitAsync(ct); }, cancellationToken); + /// + /// Executes an operation within a transaction with a custom retry policy, cancellation token support and returns a result. + /// + /// The type of the result returned by the operation. + /// The operation to execute within the transaction with cancellation token support. + /// The custom retry policy to use for this operation. + /// The transaction mode to use. Default is SerializableRw. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns the result. + /// + /// Executes the provided function within a transaction with the specified custom retry policy and cancellation support. + /// The transaction is automatically committed on success or rolled back on failure. + /// The connection and transaction are automatically managed and disposed. + /// public Task ExecuteInTransactionAsync( Func> func, IRetryPolicy retryPolicy, @@ -385,6 +726,24 @@ public Task ExecuteInTransactionAsync( return result; }, cancellationToken); + /// + /// Asynchronously creates and opens a new with retry policy support. + /// + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns an opened . + /// + /// Creates a new connection and opens it asynchronously with automatic retry logic for transient failures. + /// The connection should be disposed when no longer needed. + /// + /// + /// Important limitations: + /// + /// - Retryable connections do not support interactive transactions. Use ExecuteInTransactionAsync methods instead. + /// + /// + /// - On large result sets, these connections may cause as they read all data into memory. Use with caution. + /// + /// public async ValueTask OpenRetryableConnectionAsync(CancellationToken cancellationToken = default) { var ydbConnection = CreateDbConnection(); @@ -401,6 +760,25 @@ public async ValueTask OpenRetryableConnectionAsync(CancellationT } } + /// + /// Asynchronously creates and opens a new with a custom . + /// + /// The to use for opening the connection. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns an opened . + /// + /// Creates a new connection and opens it asynchronously with the specified . + /// The connection should be disposed when no longer needed. + /// + /// + /// Important limitations: + /// + /// - Retryable connections do not support interactive transactions. Use ExecuteInTransactionAsync methods instead. + /// + /// + /// - On large result sets, these connections may cause as they read all data into memory. Use with caution. + /// + /// public async ValueTask OpenRetryableConnectionAsync( YdbRetryPolicyConfig ydbRetryPolicyConfig, CancellationToken cancellationToken = default @@ -420,6 +798,26 @@ public async ValueTask OpenRetryableConnectionAsync( } } + /// + /// Asynchronously creates and opens a new with a custom retry policy. + /// + /// The custom retry policy to use for opening the connection. + /// A token to cancel the operation. + /// A task representing the asynchronous operation that returns an opened . + /// + /// Creates a new connection and opens it asynchronously with the specified custom retry policy. + /// The connection should be disposed when no longer needed. + /// + /// Important limitations: + /// + /// - Retryable connections do not support interactive transactions. + /// Use ExecuteInTransactionAsync methods instead. + /// + /// + /// - On large result sets, these connections may cause OutOfMemoryException as they read all data into memory. + /// Use with caution. + /// + /// public async ValueTask OpenRetryableConnectionAsync( IRetryPolicy retryPolicy, CancellationToken cancellationToken = default diff --git a/src/Ydb.Sdk/src/Ado/YdbDataSourceBuilder.cs b/src/Ydb.Sdk/src/Ado/YdbDataSourceBuilder.cs index e1c3ad0e..43a4b568 100644 --- a/src/Ydb.Sdk/src/Ado/YdbDataSourceBuilder.cs +++ b/src/Ydb.Sdk/src/Ado/YdbDataSourceBuilder.cs @@ -2,34 +2,89 @@ namespace Ydb.Sdk.Ado; +/// +/// Provides a simple way to create and configure a . +/// +/// +/// YdbDataSourceBuilder provides a fluent interface for configuring connection strings +/// and retry policies before building a YdbDataSource instance. It supports both +/// string-based and strongly-typed connection string configuration. +/// +/// +/// For more information about YDB, see: +/// YDB Documentation. +/// +/// public class YdbDataSourceBuilder { + /// + /// Initializes a new instance of the class with default settings. + /// + /// + /// Creates a new builder with default connection string and retry policy settings. + /// public YdbDataSourceBuilder() { ConnectionStringBuilder = new YdbConnectionStringBuilder(); } + /// + /// Initializes a new instance of the class with the specified connection string. + /// + /// The connection string to use for the data source. + /// + /// Creates a new builder with the specified connection string and default retry policy. + /// public YdbDataSourceBuilder(string connectionString) { ConnectionStringBuilder = new YdbConnectionStringBuilder(connectionString); } + /// + /// Initializes a new instance of the class with the specified connection string builder. + /// + /// The connection string builder to use for the data source. + /// + /// Creates a new builder with the specified connection string builder and default retry policy. + /// public YdbDataSourceBuilder(YdbConnectionStringBuilder connectionStringBuilder) { ConnectionStringBuilder = connectionStringBuilder; } /// - /// A connection string builder that can be used to configure the connection string on the builder. + /// Gets the connection string builder that can be used to configure the connection string. /// + /// + /// Provides strongly-typed properties for configuring YDB connection parameters. + /// Changes to this builder will be reflected in the built data source. + /// public YdbConnectionStringBuilder ConnectionStringBuilder { get; } /// - /// Returns the connection string, as currently configured on the builder. + /// Gets the connection string as currently configured on the builder. /// + /// + /// Returns the current connection string based on the configuration in the ConnectionStringBuilder. + /// public string ConnectionString => ConnectionStringBuilder.ConnectionString; + /// + /// Gets or sets the default retry policy for the data source. + /// + /// + /// Specifies the retry policy to use for handling transient failures. + /// Default value: with default configuration . + /// public IRetryPolicy RetryPolicy { get; set; } = new YdbRetryPolicy(YdbRetryPolicyConfig.Default); + /// + /// Builds a new instance with the current configuration. + /// + /// A new YdbDataSource instance configured with the current settings. + /// + /// Creates a new data source with the configured connection string and retry policy. + /// The builder can be reused to create multiple data sources with different configurations. + /// public YdbDataSource Build() => new(this); } diff --git a/src/Ydb.Sdk/src/Ado/YdbException.cs b/src/Ydb.Sdk/src/Ado/YdbException.cs index afadbefc..f5244f8c 100644 --- a/src/Ydb.Sdk/src/Ado/YdbException.cs +++ b/src/Ydb.Sdk/src/Ado/YdbException.cs @@ -5,16 +5,38 @@ namespace Ydb.Sdk.Ado; +/// +/// The exception that is thrown when a YDB operation fails. +/// +/// +/// YdbException is thrown when YDB operations encounter errors. +/// It provides access to YDB-specific error codes and issues. +/// Purely Ydb.Sdk-related issues which aren't related to the server will be raised +/// via the standard CLR exceptions (e.g. ArgumentException). +/// public class YdbException : DbException { + /// + /// Initializes a new instance of the class with a specified error message. + /// + /// The message that describes the error. internal YdbException(string message) : base(message) { } + /// + /// Initializes a new instance of the class from an RPC exception. + /// + /// The that caused this YDB exception. internal YdbException(RpcException e) : this(e.Status.Code(), "Transport RPC call error", e) { } + /// + /// Initializes a new instance of the class from server response status and issues. + /// + /// The status code returned by the YDB server. + /// The list of issues returned by the YDB server. internal static YdbException FromServer(StatusIds.Types.StatusCode statusCode, IReadOnlyList issues) { var code = statusCode.Code(); @@ -23,6 +45,14 @@ internal static YdbException FromServer(StatusIds.Types.StatusCode statusCode, I return new YdbException(code, message); } + /// + /// Initializes a new instance of the class with a specified status code, error message, + /// and optional inner exception. + /// + /// The YDB status code associated with this exception. + /// The message that describes the error. + /// The exception that is the cause of the current exception + /// or null if no inner exception is specified. internal YdbException(StatusCode statusCode, string message, Exception? innerException = null) : base(message, innerException) { @@ -31,14 +61,34 @@ internal YdbException(StatusCode statusCode, string message, Exception? innerExc // TODO: Add SQLSTATE message with order with https://en.wikipedia.org/wiki/SQLSTATE } + /// public override bool IsTransient { get; } + /// + /// Gets the YDB status code associated with this exception. + /// + /// + /// The status code provides detailed information about the type of error that occurred. + /// This can be used to determine the appropriate error handling strategy. + /// public StatusCode Code { get; } } +/// +/// The exception that is thrown when an operation is attempted on a +/// that already has an operation in progress. +/// +/// +/// YdbOperationInProgressException is thrown when attempting to execute a command on a +/// that is already executing another command. does not support concurrent operations. +/// public class YdbOperationInProgressException : InvalidOperationException { - public YdbOperationInProgressException(YdbConnection ydbConnection) + /// + /// Initializes a new instance of the class. + /// + /// The that has an operation in progress. + internal YdbOperationInProgressException(YdbConnection ydbConnection) : base("A command is already in progress: " + ydbConnection.LastCommand) { } diff --git a/src/Ydb.Sdk/src/Ado/YdbParameter.cs b/src/Ydb.Sdk/src/Ado/YdbParameter.cs index f7e55d29..2647a1e7 100644 --- a/src/Ydb.Sdk/src/Ado/YdbParameter.cs +++ b/src/Ydb.Sdk/src/Ado/YdbParameter.cs @@ -9,6 +9,14 @@ namespace Ydb.Sdk.Ado; +/// +/// Represents a parameter to a and optionally its mapping to a DataSet column. +/// This class cannot be inherited. +/// +/// +/// YdbParameter provides a way to pass parameters to YDB commands, supporting both standard ADO.NET DbType +/// and YDB-specific YdbDbType values. It handles type conversion and null value representation for YDB operations. +/// public sealed class YdbParameter : DbParameter { private static readonly TypedValue NullDefaultDecimal = NullDecimal(22, 9); @@ -44,16 +52,31 @@ public sealed class YdbParameter : DbParameter private string _parameterName = string.Empty; + /// + /// Initializes a new instance of the class. + /// public YdbParameter() { } + /// + /// Initializes a new instance of the class with the specified parameter name and value. + /// + /// The name of the parameter. + /// The value of the parameter. public YdbParameter(string parameterName, object value) { ParameterName = parameterName; Value = value; } + /// + /// Initializes a new instance of the class with the specified parameter name, + /// database type, and optional value. + /// + /// The name of the parameter. + /// The of the parameter. + /// The value of the parameter, or null if not specified. public YdbParameter(string parameterName, DbType dbType, object? value = null) { ParameterName = parameterName; @@ -61,6 +84,13 @@ public YdbParameter(string parameterName, DbType dbType, object? value = null) Value = value; } + /// + /// Initializes a new instance of the class with the specified parameter name, + /// YDB database type, and optional value. + /// + /// The name of the parameter. + /// The of the parameter. + /// The value of the parameter, or null if not specified. public YdbParameter(string parameterName, YdbDbType ydbDbType, object? value = null) { ParameterName = parameterName; @@ -68,6 +98,12 @@ public YdbParameter(string parameterName, YdbDbType ydbDbType, object? value = n Value = value; } + /// + /// Resets the DbType property to its original state. + /// + /// + /// This method resets the YdbDbType to Unspecified, DbType to Object, and IsNullable to false. + /// public override void ResetDbType() { YdbDbType = YdbDbType.Unspecified; @@ -75,10 +111,24 @@ public override void ResetDbType() IsNullable = false; } + /// + /// Gets or sets the YDB database type of the parameter. + /// + /// + /// YdbDbType provides YDB-specific data types that may not have direct equivalents in standard DbType. + /// When set, this property automatically updates the corresponding DbType value. + /// public YdbDbType YdbDbType { get; set; } = YdbDbType.Unspecified; private DbType _dbType = DbType.Object; + /// + /// Gets or sets the DbType of the parameter. + /// + /// + /// When setting the DbType, the corresponding YdbDbType is automatically updated. + /// This ensures compatibility with standard ADO.NET while maintaining YDB-specific functionality. + /// public override DbType DbType { get => _dbType; @@ -90,9 +140,25 @@ public override DbType DbType } public override ParameterDirection Direction { get; set; } = ParameterDirection.Input; + public override DataRowVersion SourceVersion { get; set; } = DataRowVersion.Current; + + /// + /// Gets or sets a value indicating whether the parameter accepts null values. + /// + /// + /// When true, the parameter can accept null values. This affects how null values + /// are handled during parameter binding and execution. + /// public override bool IsNullable { get; set; } + /// + /// Gets or sets the name of the parameter. + /// + /// + /// The parameter name is automatically formatted to use YDB's parameter syntax ($parameterName). + /// If the name starts with @, it's converted to $ syntax. If it doesn't start with $, the $ prefix is added. + /// [AllowNull] [DefaultValue("")] public override string ParameterName @@ -117,11 +183,35 @@ public override string SourceColumn set => _sourceColumn = value ?? string.Empty; } + /// + /// Gets or sets the value of the parameter. + /// + /// + /// The value can be any object that is compatible with the parameter's data type. + /// Null values are handled according to the IsNullable property setting. + /// public override object? Value { get; set; } + public override bool SourceColumnNullMapping { get; set; } + public override int Size { get; set; } + /// + /// Gets or sets the number of digits used to represent the Value property. + /// + /// + /// This property is used for decimal data type to specify + /// the total number of digits to the left and right of the decimal point. + /// public override byte Precision { get; set; } + + /// + /// Gets or sets the number of decimal places to which Value is resolved. + /// + /// + /// This property is used for decimal data type to specify + /// the number of digits to the right of the decimal point. + /// public override byte Scale { get; set; } internal TypedValue TypedValue diff --git a/src/Ydb.Sdk/src/Ado/YdbParameterCollection.cs b/src/Ydb.Sdk/src/Ado/YdbParameterCollection.cs index d9f4f725..69e2816f 100644 --- a/src/Ydb.Sdk/src/Ado/YdbParameterCollection.cs +++ b/src/Ydb.Sdk/src/Ado/YdbParameterCollection.cs @@ -4,6 +4,15 @@ namespace Ydb.Sdk.Ado; +/// +/// Collects all parameters relevant to a as well as their respective mappings to DataSet columns. +/// This class cannot be inherited. +/// +/// +/// YdbParameterCollection provides a strongly-typed collection of objects +/// used with YDB commands. It supports both indexed and named parameter access, and provides +/// methods for adding, removing, and managing parameters. +/// public sealed class YdbParameterCollection : DbParameterCollection, IList { private readonly List _parameters = new(5); @@ -28,16 +37,24 @@ internal YdbParameterCollection() /// data type and value. /// /// The name of the . - /// One of the NpgsqlDbType values. + /// One of the values. /// The value of the to add to the collection. /// The parameter that was added. public void AddWithValue(string parameterName, DbType parameterType, object? value = null) => Add(new YdbParameter(parameterName, parameterType) { Value = value }); - /// + /// + /// Adds a to the collection. + /// + /// The to add to the collection. void ICollection.Add(YdbParameter item) => Add(item); - /// + /// + /// Adds a parameter to the collection. + /// + /// The parameter to add to the collection. + /// The index of the added parameter. + /// Thrown when the value is not of type . public override int Add(object value) => Add(Cast(value)); /// @@ -63,10 +80,18 @@ public int Add(YdbParameter item) /// True if the parameter was found, otherwise false. public bool Contains(YdbParameter item) => _parameters.Contains(item); - /// + /// + /// Determines whether the collection contains a specific parameter. + /// + /// The parameter to locate in the collection. + /// true if the parameter is found in the collection; otherwise, false. public override bool Contains(object value) => _parameters.Contains(value); - /// + /// + /// Copies the elements of the collection to an array, starting at a particular array index. + /// + /// The one-dimensional array that is the destination of the elements copied from the collection. + /// The zero-based index in array at which copying begins. public void CopyTo(YdbParameter[] array, int arrayIndex) => _parameters.CopyTo(array, arrayIndex); /// @@ -76,10 +101,19 @@ public int Add(YdbParameter item) /// True if the parameter was found and removed, otherwise false. public bool Remove(YdbParameter item) => _parameters.Remove(item); - /// + /// + /// Determines the index of a specific parameter in the collection. + /// + /// The parameter to locate in the collection. + /// The index of the parameter if found in the collection; otherwise, -1. public override int IndexOf(object? value) => _parameters.IndexOf(Cast(value)); - /// + /// + /// Inserts a parameter into the collection at the specified index. + /// + /// The zero-based index at which the parameter should be inserted. + /// The parameter to insert into the collection. + /// Thrown when the value is not of type . public override void Insert(int index, object value) => _parameters.Insert(index, Cast(value)); /// @@ -95,7 +129,11 @@ public int Add(YdbParameter item) /// Index of the parameter, or -1 if the parameter is not present. public int IndexOf(YdbParameter item) => _parameters.IndexOf(item); - /// + /// + /// Inserts a into the collection at the specified index. + /// + /// The zero-based index at which the parameter should be inserted. + /// The to insert into the collection. public void Insert(int index, YdbParameter item) => _parameters[index] = item; /// @@ -115,13 +153,25 @@ public int Add(YdbParameter item) set => _parameters[index] = value; } - /// + /// + /// Removes the with the specified name from the collection. + /// + /// The name of the parameter to remove. public override void RemoveAt(string parameterName) => RemoveAt(IndexOf(parameterName)); - /// + /// + /// Sets the parameter at the specified index. + /// + /// The zero-based index of the parameter to set. + /// The new parameter value. protected override void SetParameter(int index, DbParameter value) => Insert(index, Cast(value)); - /// + /// + /// Sets the parameter with the specified name. + /// + /// The name of the parameter to set. + /// The new parameter value. + /// Thrown when the parameter with the specified name is not found. protected override void SetParameter(string parameterName, DbParameter value) { ArgumentNullException.ThrowIfNull(value); @@ -141,10 +191,17 @@ protected override void SetParameter(string parameterName, DbParameter value) /// The number of objects in the collection. public override int Count => _parameters.Count; - /// + /// + /// Gets an object that can be used to synchronize access to the collection. + /// + /// An object that can be used to synchronize access to the collection. public override object SyncRoot => ((ICollection)_parameters).SyncRoot; - /// + /// + /// Gets the location of a in the collection. + /// + /// The name of the parameter to find. + /// The zero-based location of the within the collection. public override int IndexOf(string parameterName) { for (var i = 0; i < _parameters.Count; i++) @@ -158,22 +215,45 @@ public override int IndexOf(string parameterName) return -1; } - /// + /// + /// Indicates whether a with the specified name exists in the collection. + /// + /// The name of the parameter to find. + /// true if the collection contains the parameter; otherwise, false. public override bool Contains(string parameterName) => IndexOf(parameterName) != -1; - /// + /// + /// Copies the elements of the collection to an array, starting at a particular array index. + /// + /// The one-dimensional array that is the destination of the elements copied from the collection. + /// The zero-based index in array at which copying begins. public override void CopyTo(Array array, int index) => ((ICollection)_parameters).CopyTo(array, index); - /// + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator that can be used to iterate through the collection. IEnumerator IEnumerable.GetEnumerator() => _parameters.GetEnumerator(); - /// + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator that can be used to iterate through the collection. public override IEnumerator GetEnumerator() => _parameters.GetEnumerator(); - /// + /// + /// Gets the parameter at the specified index. + /// + /// The zero-based index of the parameter to retrieve. + /// The at the specified index. protected override YdbParameter GetParameter(int index) => this[index]; - /// + /// + /// Gets the parameter with the specified name. + /// + /// The name of the parameter to retrieve. + /// The with the specified name. + /// Thrown when the parameter with the specified name is not found. protected override YdbParameter GetParameter(string parameterName) { var index = IndexOf(parameterName); @@ -184,7 +264,11 @@ protected override YdbParameter GetParameter(string parameterName) return _parameters[index]; } - /// + /// + /// Adds an array of parameters to the collection. + /// + /// An array of parameters to add to the collection. + /// Thrown when any value in the array is not of type . public override void AddRange(Array values) { foreach (var parameter in values) diff --git a/src/Ydb.Sdk/src/Ado/YdbProviderFactory.cs b/src/Ydb.Sdk/src/Ado/YdbProviderFactory.cs index 9f6731be..5e2afed1 100644 --- a/src/Ydb.Sdk/src/Ado/YdbProviderFactory.cs +++ b/src/Ydb.Sdk/src/Ado/YdbProviderFactory.cs @@ -2,19 +2,80 @@ namespace Ydb.Sdk.Ado; +/// +/// Represents a set of methods for creating instances of a provider's implementation of the data source classes. +/// +/// +/// YdbProviderFactory is the factory class for creating YDB-specific data source objects. +/// It provides methods to create connections, commands, parameters, and other ADO.NET objects +/// that are specific to the YDB database provider. +/// +/// +/// For more information about YDB, see: +/// YDB Documentation. +/// +/// public class YdbProviderFactory : DbProviderFactory { + /// + /// Gets the singleton instance of the YdbProviderFactory. + /// + /// + /// This static instance can be used to create YDB-specific ADO.NET objects + /// without instantiating the factory class directly. + /// public static readonly YdbProviderFactory Instance = new(); + /// + /// Returns a strongly typed object. + /// + /// A new instance of . + /// + /// Creates a new YDB command object that can be used to execute SQL statements + /// and stored procedures against a YDB database. + /// public override YdbCommand CreateCommand() => new(); + /// + /// Returns a strongly typed object. + /// + /// A new instance of . + /// + /// Creates a new YDB connection object that can be used to connect to a YDB database. + /// The connection must be opened before it can be used for database operations. + /// public override YdbConnection CreateConnection() => new(); + /// + /// Returns a strongly typed object. + /// + /// A new instance of . + /// + /// Creates a new YDB connection string builder that provides strongly-typed properties + /// for building YDB connection strings with validation and IntelliSense support. + /// public override YdbConnectionStringBuilder CreateConnectionStringBuilder() => new(); + /// + /// Returns a strongly typed object. + /// + /// A new instance of . + /// + /// Creates a new YDB parameter object that can be used to pass parameters + /// to YDB commands. The parameter supports YDB-specific data types and features. + /// public override DbParameter CreateParameter() => new YdbParameter(); #if NET7_0_OR_GREATER + /// + /// Returns a strongly typed object. + /// + /// The connection string to use for the data source. + /// A new instance of with the specified connection string. + /// + /// Creates a new YDB data source object that provides a modern, lightweight way to work with YDB. + /// The data source is available only in .NET 7.0 and later versions. + /// public override YdbDataSource CreateDataSource(string connectionString) => new(); #endif } diff --git a/src/Ydb.Sdk/src/Ado/YdbTransaction.cs b/src/Ydb.Sdk/src/Ado/YdbTransaction.cs index de22c891..6bd669d9 100644 --- a/src/Ydb.Sdk/src/Ado/YdbTransaction.cs +++ b/src/Ydb.Sdk/src/Ado/YdbTransaction.cs @@ -5,6 +5,19 @@ namespace Ydb.Sdk.Ado; +/// +/// Represents a YDB transaction. This class cannot be inherited. +/// +/// +/// YdbTransaction represents a database transaction in YDB. It provides methods to commit or rollback +/// changes made within the transaction. The transaction mode determines the isolation level and +/// consistency guarantees. +/// +/// +/// For more information about YDB transaction modes, see: +/// YDB Transactions Documentation. +/// +/// public sealed class YdbTransaction : DbTransaction { private readonly TransactionMode _transactionMode; @@ -13,9 +26,32 @@ public sealed class YdbTransaction : DbTransaction private YdbConnection? _ydbConnection; private bool _isDisposed; + /// + /// Gets or sets the transaction identifier. + /// + /// + /// The transaction ID is assigned by YDB when the transaction is started. + /// This property is used internally for transaction management. + /// internal string? TxId { get; set; } + + /// + /// Gets a value indicating whether the transaction has been completed. + /// + /// + /// A transaction is considered completed when it has been committed, rolled back, or failed. + /// Once completed, the transaction cannot be used for further operations. + /// internal bool Completed { get; private set; } + /// + /// Gets or sets a value indicating whether the transaction has failed. + /// + /// + /// When true, indicates that the transaction has been rolled back by the server. + /// A failed transaction cannot be committed. The method + /// can be called to mark the transaction as completed. + /// internal bool Failed { private get => _failed; @@ -26,6 +62,13 @@ internal bool Failed } } + /// + /// Gets the transaction control for YDB operations. + /// + /// + /// Returns null if the transaction is completed, otherwise returns the appropriate + /// transaction control based on whether the transaction has been started. + /// internal TransactionControl? TransactionControl => Completed ? null : TxId == null @@ -38,13 +81,65 @@ internal YdbTransaction(YdbConnection ydbConnection, TransactionMode transaction _transactionMode = transactionMode; } + /// + /// Commits the database transaction. + /// + /// + /// Thrown when the transaction has already been completed or the connection is closed. + /// + /// + /// Thrown when another operation is in progress on the connection. + /// + /// + /// Thrown when the commit operation fails. + /// public override void Commit() => CommitAsync().GetAwaiter().GetResult(); + /// + /// Asynchronously commits the database transaction. + /// + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Thrown when the transaction has already been completed or the connection is closed. + /// + /// + /// Thrown when another operation is in progress on the connection. + /// + /// + /// Thrown when the commit operation fails. + /// public override async Task CommitAsync(CancellationToken cancellationToken = new()) => await FinishTransaction(txId => DbConnection!.Session.CommitTransaction(txId, cancellationToken)); + /// + /// Rolls back the database transaction. + /// + /// + /// Thrown when the transaction has already been completed or the connection is closed. + /// + /// + /// Thrown when another operation is in progress on the connection. + /// + /// + /// Thrown when the rollback operation fails. + /// public override void Rollback() => RollbackAsync().GetAwaiter().GetResult(); + /// + /// Asynchronously rolls back the database transaction. + /// + /// A token to cancel the operation. + /// A task representing the asynchronous operation. + /// + /// Thrown when the transaction has already been completed or the connection is closed. + /// + /// + /// Thrown when another operation is in progress on the connection. + /// + /// + /// Thrown when the rollback operation fails. + /// public override async Task RollbackAsync(CancellationToken cancellationToken = new()) { if (Failed) @@ -57,6 +152,13 @@ internal YdbTransaction(YdbConnection ydbConnection, TransactionMode transaction await FinishTransaction(txId => DbConnection!.Session.RollbackTransaction(txId, cancellationToken)); } + /// + /// Gets the database connection associated with this transaction. + /// + /// The YdbConnection associated with this transaction, or null if disposed. + /// + /// Thrown when the transaction has been disposed. + /// protected override YdbConnection? DbConnection { get @@ -66,6 +168,13 @@ protected override YdbConnection? DbConnection } } + /// + /// Gets the isolation level of this transaction. + /// + /// + /// Returns Serializable for SerializableRw transaction mode, otherwise Unspecified. + /// The actual isolation level depends on the transaction mode used when creating the transaction. + /// public override IsolationLevel IsolationLevel => _transactionMode == TransactionMode.SerializableRw ? IsolationLevel.Serializable : IsolationLevel.Unspecified; @@ -107,6 +216,13 @@ private async Task FinishTransaction(Func finishMethod) } } + /// + /// Releases the unmanaged resources used by the YdbTransaction and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + /// + /// If the transaction is not completed, it will be rolled back before disposal. + /// protected override void Dispose(bool disposing) { if (_isDisposed || !disposing) @@ -120,6 +236,13 @@ protected override void Dispose(bool disposing) _isDisposed = true; } + /// + /// Asynchronously releases the unmanaged resources used by the YdbTransaction. + /// + /// A ValueTask representing the asynchronous disposal operation. + /// + /// If the transaction is not completed, it will be rolled back before disposal. + /// public override async ValueTask DisposeAsync() { if (_isDisposed) diff --git a/src/Ydb.Sdk/src/Ado/YdbType/YdbDbType.cs b/src/Ydb.Sdk/src/Ado/YdbType/YdbDbType.cs index 6633c00e..dd2a1f27 100644 --- a/src/Ydb.Sdk/src/Ado/YdbType/YdbDbType.cs +++ b/src/Ydb.Sdk/src/Ado/YdbType/YdbDbType.cs @@ -3,10 +3,27 @@ namespace Ydb.Sdk.Ado.YdbType; /// -/// See YDB Primitive Types for details. +/// Specifies the data type of the . /// +/// +/// YdbDbType represents the primitive data types supported by YDB. +/// +/// +/// For more information about YDB primitive types, see: +/// YDB Primitive Types Documentation. +/// +/// public enum YdbDbType { + /// + /// Unspecified data type. + /// + /// + /// When this type is used, the tries to automatically determine + /// the appropriate YDB data type based on the system type of the parameter value. + /// This provides convenience, but it may not always match the intended YDB type and + /// doesn't support null values. + /// Unspecified, /// @@ -86,6 +103,7 @@ public enum YdbDbType /// /// /// Precision and Scale are specified in the . + /// If not specified, the default values (precision: 22, scale: 9) are used. /// Decimal, @@ -164,16 +182,44 @@ public enum YdbDbType /// /// /// Value range: From -136 years to +136 years. Internal representation: Signed 64-bit integer. - /// Can't be used in the primary key. /// Interval, + /// + /// Date with extended range, precision to the day. + /// + /// + /// Extended range date type that supports dates before 01.01.1970 and beyond the standard Date range. + /// Provides better support for historical dates and future dates. + /// Date32, + /// + /// Date/time with extended range, precision to the second. + /// + /// + /// Extended range datetime type that supports date/time values before 01.01.1970 and + /// beyond the standard Datetime range. + /// Provides better support for historical timestamps and future timestamps. + /// Datetime64, + /// + /// Date/time with extended range, precision to the microsecond. + /// + /// + /// Extended range timestamp type that supports microsecond-precision timestamps + /// before 01.01.1970 and beyond the standard Timestamp range. Provides better support for historical and future timestamps. + /// Timestamp64, + /// + /// Time interval with extended range, precision to microseconds. + /// + /// + /// Extended range interval type that supports larger time intervals + /// beyond the standard Interval range. + /// Interval64 } diff --git a/src/Ydb.Sdk/src/Auth/ICredentialsProvider.cs b/src/Ydb.Sdk/src/Auth/ICredentialsProvider.cs index e327c73a..92618bff 100644 --- a/src/Ydb.Sdk/src/Auth/ICredentialsProvider.cs +++ b/src/Ydb.Sdk/src/Auth/ICredentialsProvider.cs @@ -1,10 +1,27 @@ namespace Ydb.Sdk.Auth; +/// +/// Interface for providing authentication credentials to YDB. +/// +/// +/// ICredentialsProvider defines the contract for authentication credential providers. +/// Implementations should handle token retrieval and refresh as needed. +/// public interface ICredentialsProvider { + /// + /// Gets the authentication information asynchronously. + /// + /// + /// A value task that represents the asynchronous operation. + /// The task result contains the authentication token. + /// ValueTask GetAuthInfoAsync(); } +/// +/// Interface for authentication clients. +/// public interface IAuthClient { Task FetchToken(); diff --git a/src/Ydb.Sdk/src/Auth/TokenProvider.cs b/src/Ydb.Sdk/src/Auth/TokenProvider.cs index 84874d37..93d21aae 100644 --- a/src/Ydb.Sdk/src/Auth/TokenProvider.cs +++ b/src/Ydb.Sdk/src/Auth/TokenProvider.cs @@ -1,9 +1,20 @@ namespace Ydb.Sdk.Auth; +/// +/// Token-based authentication provider for YDB. +/// +/// +/// TokenProvider provides authentication using a static access token. +/// This is suitable for scenarios where you have a pre-obtained token. +/// public class TokenProvider : ICredentialsProvider { private readonly string _token; + /// + /// Initializes a new instance of the TokenProvider class. + /// + /// The access token to use for authentication. public TokenProvider(string token) { _token = token; diff --git a/src/Ydb.Sdk/src/Driver.cs b/src/Ydb.Sdk/src/Driver.cs index de842a76..66b989b9 100644 --- a/src/Ydb.Sdk/src/Driver.cs +++ b/src/Ydb.Sdk/src/Driver.cs @@ -10,14 +10,29 @@ namespace Ydb.Sdk; +/// +/// Main YDB driver implementation that handles endpoint discovery and connection management. +/// +/// +/// The Driver class provides the primary interface for connecting to YDB clusters. +/// It automatically discovers available endpoints and manages gRPC connections. +/// public sealed class Driver : BaseDriver { private const int AttemptDiscovery = 10; private readonly EndpointPool _endpointPool; + /// + /// Gets the database path for this driver instance. + /// internal string Database => Config.Database; + /// + /// Initializes a new instance of the Driver class. + /// + /// Driver configuration settings. + /// Optional logger factory for logging. If null, NullLoggerFactory will be used. public Driver(DriverConfig config, ILoggerFactory? loggerFactory = null) : base(config, loggerFactory ?? NullLoggerFactory.Instance, (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger() @@ -26,6 +41,13 @@ public Driver(DriverConfig config, ILoggerFactory? loggerFactory = null) _endpointPool = new EndpointPool(LoggerFactory); } + /// + /// Creates and initializes a new Driver instance in one operation. + /// + /// Driver configuration settings. + /// Optional logger factory for logging. If null, NullLoggerFactory will be used. + /// A fully initialized Driver instance ready for use. + /// Thrown when endpoint discovery fails after all retry attempts. public static async Task CreateInitialized(DriverConfig config, ILoggerFactory? loggerFactory = null) { var driver = new Driver(config, loggerFactory); @@ -33,6 +55,14 @@ public static async Task CreateInitialized(DriverConfig config, ILoggerF return driver; } + /// + /// Initializes the driver by discovering available endpoints. + /// + /// + /// This method performs initial endpoint discovery and starts periodic discovery. + /// It will retry up to 10 times with exponential backoff if discovery fails. + /// + /// Thrown when endpoint discovery fails after all retry attempts. public async Task Initialize() { Logger.LogInformation("Started initial endpoint discovery"); diff --git a/src/Ydb.Sdk/src/DriverConfig.cs b/src/Ydb.Sdk/src/DriverConfig.cs index 2568a156..104adb02 100644 --- a/src/Ydb.Sdk/src/DriverConfig.cs +++ b/src/Ydb.Sdk/src/DriverConfig.cs @@ -4,29 +4,73 @@ namespace Ydb.Sdk; +/// +/// Configuration settings for YDB driver. +/// +/// +/// DriverConfig contains all the necessary settings to configure a YDB driver instance, +/// including connection parameters, timeouts, and authentication credentials. +/// public class DriverConfig { private readonly string _pid = Environment.ProcessId.ToString(); + /// + /// Gets the YDB server endpoint URL. + /// public string Endpoint { get; } + + /// + /// Gets the database path. + /// public string Database { get; } + + /// + /// Gets the credentials provider for authentication. + /// public ICredentialsProvider? Credentials { get; } + /// + /// Gets or sets the connection timeout. + /// public TimeSpan ConnectTimeout { get; init; } = TimeSpan.FromSeconds(GrpcDefaultSettings.ConnectTimeoutSeconds); + /// + /// Gets or sets the keep-alive ping delay. + /// public TimeSpan KeepAlivePingDelay { get; init; } = TimeSpan.FromSeconds(GrpcDefaultSettings.KeepAlivePingSeconds); + /// + /// Gets or sets the keep-alive ping timeout. + /// public TimeSpan KeepAlivePingTimeout { get; init; } = TimeSpan.FromSeconds(GrpcDefaultSettings.KeepAlivePingTimeoutSeconds); + /// + /// Gets or sets the username for basic authentication. + /// public string? User { get; init; } + + /// + /// Gets or sets the password for basic authentication. + /// public string? Password { get; init; } + /// + /// Gets or sets a value indicating whether to enable multiple HTTP/2 connections. + /// public bool EnableMultipleHttp2Connections { get; init; } = GrpcDefaultSettings.EnableMultipleHttp2Connections; + /// + /// Gets or sets the maximum send message size in bytes. + /// public int MaxSendMessageSize { get; init; } = GrpcDefaultSettings.MaxSendMessageSize; + + /// + /// Gets or sets the maximum receive message size in bytes. + /// public int MaxReceiveMessageSize { get; init; } = GrpcDefaultSettings.MaxReceiveMessageSize; internal X509Certificate2Collection CustomServerCertificates { get; } = new(); @@ -34,6 +78,14 @@ public class DriverConfig internal TimeSpan EndpointDiscoveryTimeout = TimeSpan.FromSeconds(10); internal string SdkVersion { get; } + /// + /// Initializes a new instance of the DriverConfig class. + /// + /// The YDB server endpoint URL. + /// The database path. + /// Optional credentials provider for authentication. + /// Optional custom server certificate for TLS validation. + /// Optional collection of custom server certificates for TLS validation. public DriverConfig( string endpoint, string database, diff --git a/src/Ydb.Sdk/src/IDriver.cs b/src/Ydb.Sdk/src/IDriver.cs index be30ec3b..cc35106b 100644 --- a/src/Ydb.Sdk/src/IDriver.cs +++ b/src/Ydb.Sdk/src/IDriver.cs @@ -8,8 +8,24 @@ namespace Ydb.Sdk; +/// +/// Core interface for YDB driver operations. +/// +/// +/// The IDriver interface defines the contract for YDB client drivers. +/// It provides methods for executing gRPC calls and managing driver lifecycle. +/// public interface IDriver : IAsyncDisposable, IDisposable { + /// + /// Executes a unary gRPC call. + /// + /// The request message type. + /// The response message type. + /// The gRPC method to call. + /// The request message. + /// gRPC request settings. + /// A task that represents the asynchronous operation. The task result contains the response message. public Task UnaryCall( Method method, TRequest request, @@ -17,6 +33,15 @@ public Task UnaryCall( where TRequest : class where TResponse : class; + /// + /// Executes a server streaming gRPC call. + /// + /// The request message type. + /// The response message type. + /// The gRPC method to call. + /// The request message. + /// gRPC request settings. + /// A value task that represents the asynchronous operation. The task result contains the server stream. public ValueTask> ServerStreamCall( Method method, TRequest request, @@ -24,39 +49,104 @@ public ValueTask> ServerStreamCall where TRequest : class where TResponse : class; + /// + /// Executes a bidirectional streaming gRPC call. + /// + /// The request message type. + /// The response message type. + /// The gRPC method to call. + /// gRPC request settings. + /// A value task that represents the asynchronous operation. The task result contains the bidirectional stream. public ValueTask> BidirectionalStreamCall( Method method, GrpcRequestSettings settings) where TRequest : class where TResponse : class; + /// + /// Gets the logger factory used by this driver. + /// ILoggerFactory LoggerFactory { get; } + /// + /// Registers a new owner of this driver instance. + /// + /// + /// This method is used to track how many components are using this driver. + /// The driver will not be disposed until all owners are released. + /// void RegisterOwner(); + /// + /// Gets a value indicating whether this driver has been disposed. + /// bool IsDisposed { get; } } +/// +/// Represents a bidirectional gRPC stream for sending requests and receiving responses. +/// +/// The type of request messages. +/// The type of response messages. public interface IBidirectionalStream : IDisposable { + /// + /// Writes a request message to the stream. + /// + /// The request message to write. + /// A task that represents the asynchronous write operation. public Task Write(TRequest request); + /// + /// Advances the stream to the next response message. + /// + /// A task that represents the asynchronous operation. The task result indicates whether a response was available. public Task MoveNextAsync(); + /// + /// Gets the current response message. + /// public TResponse Current { get; } + /// + /// Gets the current authentication token. + /// + /// A value task that represents the asynchronous operation. The task result contains the authentication token. public ValueTask AuthToken(); + /// + /// Completes the request stream. + /// + /// A task that represents the asynchronous operation. public Task RequestStreamComplete(); } +/// +/// Represents a server streaming gRPC stream for receiving response messages. +/// +/// The type of response messages. public interface IServerStream : IDisposable { + /// + /// Advances the stream to the next response message. + /// + /// A cancellation token to cancel the operation. + /// A task that represents the asynchronous operation. The task result indicates whether a response was available. public Task MoveNextAsync(CancellationToken cancellationToken = default); + /// + /// Gets the current response message. + /// public TResponse Current { get; } } +/// +/// Base implementation of the IDriver interface providing common functionality. +/// +/// +/// BaseDriver provides the core implementation for YDB drivers including gRPC channel management, +/// authentication handling, request metadata management, and error handling. +/// public abstract class BaseDriver : IDriver { private readonly ICredentialsProvider? _credentialsProvider; diff --git a/src/Ydb.Sdk/src/Services/Topic/TopicClient.cs b/src/Ydb.Sdk/src/Services/Topic/TopicClient.cs index 05d17ff1..0f27ad01 100644 --- a/src/Ydb.Sdk/src/Services/Topic/TopicClient.cs +++ b/src/Ydb.Sdk/src/Services/Topic/TopicClient.cs @@ -4,10 +4,21 @@ namespace Ydb.Sdk.Services.Topic; +/// +/// Client for YDB Topic service operations. +/// +/// +/// TopicClient provides methods for managing YDB topics including creation, modification, +/// and deletion of topics and their configurations. +/// public class TopicClient { private readonly IDriver _driver; + /// + /// Initializes a new instance of the class. + /// + /// The YDB driver to use for topic operations. public TopicClient(IDriver driver) { _driver = driver;