< Summary

Line coverage
95%
Covered lines: 1164
Uncovered lines: 54
Coverable lines: 1218
Total lines: 3577
Line coverage: 95.5%
Branch coverage
76%
Covered branches: 137
Total branches: 178
Branch coverage: 76.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: Authenticate(...)100%11100%
File 1: <AuthenticateAsync()100%11100%
File 1: AuthEnable(...)100%11100%
File 1: <AuthEnableAsync()100%11100%
File 1: AuthDisable(...)100%11100%
File 1: <AuthDisableAsync()100%11100%
File 1: UserAdd(...)100%11100%
File 1: <UserAddAsync()100%11100%
File 1: UserGet(...)100%11100%
File 1: <UserGetAsync()100%11100%
File 1: UserList(...)100%11100%
File 1: <UserListAsync()100%11100%
File 1: UserDelete(...)100%11100%
File 1: <UserDeleteAsync()100%11100%
File 1: UserChangePassword(...)100%11100%
File 1: <UserChangePasswordAsync()100%11100%
File 1: UserGrantRole(...)100%11100%
File 1: <UserGrantRoleAsync()100%11100%
File 1: UserRevokeRole(...)100%11100%
File 1: <UserRevokeRoleAsync()100%11100%
File 1: RoleAdd(...)100%11100%
File 1: <RoleAddAsync()100%11100%
File 1: RoleGet(...)100%11100%
File 1: <RoleGetAsync()100%11100%
File 1: RoleList(...)100%11100%
File 1: <RoleListAsync()100%11100%
File 1: RoleDelete(...)100%11100%
File 1: <RoleDeleteAsync()100%11100%
File 1: RoleGrantPermission(...)100%11100%
File 1: <RoleGrantPermissionAsync()100%11100%
File 1: RoleRevokePermission(...)100%11100%
File 1: <RoleRevokePermissionAsync()100%11100%
File 2: MemberAdd(...)100%11100%
File 2: <MemberAddAsync()100%11100%
File 2: MemberRemove(...)100%11100%
File 2: <MemberRemoveAsync()100%11100%
File 2: MemberUpdate(...)100%11100%
File 2: <MemberUpdateAsync()100%11100%
File 2: MemberList(...)100%11100%
File 2: <MemberListAsync()100%11100%
File 3: Campaign(...)50%22100%
File 3: Campaign(...)50%44100%
File 3: <CampaignAsync()50%22100%
File 3: <CampaignAsync()50%44100%
File 3: Proclaim(...)50%22100%
File 3: Proclaim(...)50%44100%
File 3: <ProclaimAsync()50%22100%
File 3: <ProclaimAsync()50%44100%
File 3: Leader(...)50%22100%
File 3: Leader(...)50%22100%
File 3: <LeaderAsync()50%22100%
File 3: <LeaderAsync()50%22100%
File 3: ObserveAsync()100%44100%
File 3: ObserveAsync()100%44100%
File 3: Resign(...)50%22100%
File 3: Resign(...)50%22100%
File 3: <ResignAsync()50%22100%
File 3: <ResignAsync()50%22100%
File 3: Observe(...)100%22100%
File 3: Observe(...)100%22100%
File 4: GetConnection()100%11100%
File 4: GetWatchManager()100%11100%
File 4: CancelWatch(...)100%11100%
File 4: CancelWatch(...)100%22100%
File 4: get_Username()100%11100%
File 4: .ctor(...)100%11100%
File 4: .cctor()100%11100%
File 4: .ctor(...)75%8895.34%
File 4: .ctor(...)50%101091.3%
File 4: .ctor(...)83.33%66100%
File 4: .ctor(...)50%2252.94%
File 4: SetCredentials(...)50%8661.53%
File 4: ClearCredentials()100%11100%
File 4: EnsureAuthenticationSupported()50%2288.88%
File 4: RequestTokenAsync()100%22100%
File 4: Dispose(...)75%88100%
File 4: Dispose()100%11100%
File 5: Get(...)100%11100%
File 5: Get(...)100%11100%
File 5: <GetAsync()100%11100%
File 5: GetAsync()100%11100%
File 5: GetVal(...)100%22100%
File 5: GetValAsync()100%22100%
File 5: GetRange(...)100%11100%
File 5: GetRangeAsync()100%11100%
File 5: GetRangeVal(...)100%11100%
File 5: GetRangeValAsync()100%11100%
File 5: Put(...)100%11100%
File 5: Put(...)100%11100%
File 5: <PutAsync()100%11100%
File 5: PutAsync()100%11100%
File 5: Delete(...)100%11100%
File 5: Delete(...)100%11100%
File 5: <DeleteAsync()100%11100%
File 5: DeleteAsync()100%11100%
File 5: DeleteRange(...)100%11100%
File 5: DeleteRangeAsync()100%11100%
File 5: Transaction(...)100%11100%
File 5: <TransactionAsync()100%11100%
File 5: Compact(...)100%11100%
File 5: <CompactAsync()100%11100%
File 6: LeaseGrant(...)100%11100%
File 6: <LeaseGrantAsync()100%11100%
File 6: LeaseRevoke(...)100%11100%
File 6: <LeaseRevokeAsync()100%11100%
File 6: LeaseKeepAlive(...)75%4493.84%
File 6: LeaseKeepAlive()100%11100%
File 6: <LeaseKeepAlive()66.66%6686.36%
File 6: LeaseKeepAlive()100%11100%
File 6: <LeaseKeepAlive()100%11100%
File 6: LeaseKeepAlive()100%11100%
File 6: <LeaseKeepAlive()100%11100%
File 6: LeaseKeepAlive()100%11100%
File 6: <LeaseKeepAlive()100%22100%
File 6: LeaseKeepAlive()100%11100%
File 6: <LeaseKeepAlive()100%22100%
File 6: LeaseTimeToLive(...)100%11100%
File 6: <LeaseTimeToLiveAsync()100%11100%
File 7: Lock(...)100%11100%
File 7: Lock(...)100%11100%
File 7: LockAsync()100%11100%
File 7: LockAsync()100%11100%
File 7: <LockAsync()100%11100%
File 7: Unlock(...)100%11100%
File 7: Unlock(...)100%11100%
File 7: UnlockAsync()100%11100%
File 7: UnlockAsync()100%11100%
File 7: <UnlockAsync()100%11100%
File 8: Alarm(...)100%11100%
File 8: <AlarmAsync()100%11100%
File 8: Status(...)100%11100%
File 8: <StatusAsync()100%11100%
File 8: Defragment(...)100%11100%
File 8: <DefragmentAsync()100%11100%
File 8: Hash(...)100%11100%
File 8: <HashAsync()100%11100%
File 8: HashKV(...)100%11100%
File 8: <HashKVAsync()100%11100%
File 8: Snapshot()100%11100%
File 8: <Snapshot()100%22100%
File 8: Snapshot()100%11100%
File 8: <Snapshot()100%44100%
File 8: MoveLeader(...)100%11100%
File 8: <MoveLeaderAsync()100%11100%
File 9: RangeRespondToDictionary(...)100%22100%
File 9: GetRangeEnd(...)50%2275%
File 9: GetStringByteForRangeRequests(...)50%22100%
File 9: CallEtcd(...)100%11100%
File 9: CallEtcdAsync(...)100%11100%
File 9: CallEtcdAsync(...)100%11100%
File 10: WatchAsync()100%44100%
File 10: WatchAsync(...)100%44100%
File 10: Watch(...)100%44100%
File 10: Watch(...)75%4489.47%
File 10: WatchAsync(...)100%11100%
File 10: WatchAsync(...)100%22100%
File 10: WatchAsync()100%22100%
File 10: WatchAsync()75%4483.33%
File 10: WatchAsync(...)100%11100%
File 10: WatchAsync(...)100%22100%
File 10: Watch(...)100%11100%
File 10: Watch(...)100%11100%
File 10: Watch(...)100%11100%
File 10: Watch(...)100%210%
File 10: Watch(...)100%210%
File 10: Watch(...)100%22100%
File 10: Watch(...)100%11100%
File 10: Watch(...)100%210%
File 10: Watch(...)100%210%
File 10: Watch(...)100%22100%
File 10: WatchAsync(...)100%11100%
File 10: WatchAsync(...)100%210%
File 10: WatchAsync(...)100%210%
File 10: WatchAsync(...)100%22100%
File 10: WatchAsync(...)100%11100%
File 10: WatchAsync(...)100%210%
File 10: WatchAsync(...)100%210%
File 10: WatchAsync(...)100%22100%
File 10: WatchRange(...)100%11100%
File 10: WatchRange(...)100%22100%
File 10: WatchRange(...)100%22100%
File 10: WatchRange(...)100%44100%
File 10: WatchRangeAsync(...)100%11100%
File 10: WatchRangeAsync(...)100%22100%
File 10: WatchRangeAsync()100%22100%
File 10: WatchRangeAsync()100%44100%

File(s)

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/authClient.cs

#LineLine coverage
 1using System;
 2using System.Threading;
 3using System.Threading.Tasks;
 4using Etcdserverpb;
 5using Grpc.Core;
 6
 7namespace dotnet_etcd;
 8
 9public partial class EtcdClient
 10{
 11    /// <summary>
 12    ///     Authenticate processes an authenticate request.
 13    /// </summary>
 14    /// <param name="request">The request to send to the server.</param>
 15    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 16    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 17    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 18    /// <returns>The response received from the server.</returns>
 19    public AuthenticateResponse Authenticate(AuthenticateRequest request, Metadata headers = null,
 20        DateTime? deadline = null,
 621        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 622        .Authenticate(request, headers, deadline, cancellationToken));
 23
 24    /// <summary>
 25    ///     Authenticate processes an authenticate request.
 26    /// </summary>
 27    /// <param name="request">The request to send to the server.</param>
 28    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 29    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 30    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 31    /// <returns>The response received from the server.</returns>
 32    public async Task<AuthenticateResponse> AuthenticateAsync(AuthenticateRequest request,
 33        Metadata headers = null, DateTime? deadline = null,
 1034        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 1035        .AuthClient
 1036        .AuthenticateAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 37
 38    /// <summary>
 39    ///     AuthEnable enables authentication
 40    /// </summary>
 41    /// <param name="request">The request to send to the server.</param>
 42    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 43    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 44    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 45    /// <returns>The response received from the server.</returns>
 46    public AuthEnableResponse AuthEnable(AuthEnableRequest request, Metadata headers = null,
 47        DateTime? deadline = null,
 648        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 649        .AuthEnable(request, headers, deadline, cancellationToken));
 50
 51    /// <summary>
 52    ///     AuthEnableAsync enables authentication in async
 53    /// </summary>
 54    /// <param name="request">The request to send to the server.</param>
 55    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 56    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 57    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 58    /// <returns>The response received from the server.</returns>
 59    public async Task<AuthEnableResponse> AuthEnableAsync(AuthEnableRequest request,
 60        Metadata headers = null, DateTime? deadline = null,
 4061        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 4062        .AuthClient
 4063        .AuthEnableAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 64
 65    /// <summary>
 66    ///     AuthDisable disables authentication
 67    /// </summary>
 68    /// <param name="request">The request to send to the server.</param>
 69    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 70    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 71    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 72    /// <returns>The response received from the server.</returns>
 73    public AuthDisableResponse AuthDisable(AuthDisableRequest request, Metadata headers = null,
 74        DateTime? deadline = null,
 475        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 476        .AuthDisable(request, headers, deadline, cancellationToken));
 77
 78    /// <summary>
 79    ///     AuthDisableAsync disables authentication in async
 80    /// </summary>
 81    /// <param name="request">The request to send to the server.</param>
 82    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 83    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 84    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 85    /// <returns>The response received from the server.</returns>
 86    public async Task<AuthDisableResponse> AuthDisableAsync(AuthDisableRequest request,
 87        Metadata headers = null, DateTime? deadline = null,
 11288        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 11289        .AuthClient
 11290        .AuthDisableAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 91
 92    /// <summary>
 93    ///     UserAdd adds a new user
 94    /// </summary>
 95    /// <param name="request">The request to send to the server.</param>
 96    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 97    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 98    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 99    /// <returns>The response received from the server.</returns>
 100    public AuthUserAddResponse UserAdd(AuthUserAddRequest request, Metadata headers = null,
 101        DateTime? deadline = null,
 4102        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 4103        .UserAdd(request, headers, deadline, cancellationToken));
 104
 105    /// <summary>
 106    ///     UserAddAsync adds a new user in async
 107    /// </summary>
 108    /// <param name="request">The request to send to the server.</param>
 109    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 110    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 111    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 112    /// <returns>The response received from the server.</returns>
 113    public async Task<AuthUserAddResponse> UserAddAsync(AuthUserAddRequest request,
 114        Metadata headers = null, DateTime? deadline = null,
 98115        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 98116        .AuthClient
 98117        .UserAddAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 118
 119    /// <summary>
 120    ///     UserGet gets detailed user information
 121    /// </summary>
 122    /// <param name="request">The request to send to the server.</param>
 123    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 124    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 125    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 126    /// <returns>The response received from the server.</returns>
 127    public AuthUserGetResponse UserGet(AuthUserGetRequest request, Metadata headers = null,
 128        DateTime? deadline = null,
 2129        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2130        .UserGet(request, headers, deadline, cancellationToken));
 131
 132    /// <summary>
 133    ///     UserGetAsync gets detailed user information in async
 134    /// </summary>
 135    /// <param name="request">The request to send to the server.</param>
 136    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 137    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 138    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 139    /// <returns>The response received from the server.</returns>
 140    public async Task<AuthUserGetResponse> UserGetAsync(AuthUserGetRequest request,
 141        Metadata headers = null, DateTime? deadline = null,
 2142        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 2143        .AuthClient
 2144        .UserGetAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 145
 146    /// <summary>
 147    ///     UserList gets a list of all users
 148    /// </summary>
 149    /// <param name="request">The request to send to the server.</param>
 150    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 151    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 152    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 153    /// <returns>The response received from the server.</returns>
 154    public AuthUserListResponse UserList(AuthUserListRequest request, Metadata headers = null,
 155        DateTime? deadline = null,
 4156        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 4157        .UserList(request, headers, deadline, cancellationToken));
 158
 159    /// <summary>
 160    ///     UserListAsync gets a list of all users in async
 161    /// </summary>
 162    /// <param name="request">The request to send to the server.</param>
 163    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 164    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 165    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 166    /// <returns>The response received from the server.</returns>
 167    public async Task<AuthUserListResponse> UserListAsync(AuthUserListRequest request,
 168        Metadata headers = null, DateTime? deadline = null,
 68169        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 68170        .AuthClient
 68171        .UserListAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 172
 173    /// <summary>
 174    ///     UserDelete deletes a specified user
 175    /// </summary>
 176    /// <param name="request">The request to send to the server.</param>
 177    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 178    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 179    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 180    /// <returns>The response received from the server.</returns>
 181    public AuthUserDeleteResponse UserDelete(AuthUserDeleteRequest request, Metadata headers = null,
 182        DateTime? deadline = null,
 4183        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 4184        .UserDelete(request, headers, deadline, cancellationToken));
 185
 186    /// <summary>
 187    ///     UserDeleteAsync deletes a specified user in async
 188    /// </summary>
 189    /// <param name="request">The request to send to the server.</param>
 190    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 191    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 192    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 193    /// <returns>The response received from the server.</returns>
 194    public async Task<AuthUserDeleteResponse> UserDeleteAsync(AuthUserDeleteRequest request,
 195        Metadata headers = null, DateTime? deadline = null,
 64196        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 64197        .AuthClient
 64198        .UserDeleteAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 199
 200    /// <summary>
 201    ///     UserChangePassword changes the password of a specified user
 202    /// </summary>
 203    /// <param name="request">The request to send to the server.</param>
 204    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 205    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 206    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 207    /// <returns>The response received from the server.</returns>
 208    public AuthUserChangePasswordResponse UserChangePassword(AuthUserChangePasswordRequest request,
 209        Metadata headers = null, DateTime? deadline = null,
 2210        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2211        .UserChangePassword(request, headers, deadline, cancellationToken));
 212
 213    /// <summary>
 214    ///     UserChangePasswordAsync changes the password of a specified user in async
 215    /// </summary>
 216    /// <param name="request">The request to send to the server.</param>
 217    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 218    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 219    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 220    /// <returns>The response received from the server.</returns>
 221    public async Task<AuthUserChangePasswordResponse> UserChangePasswordAsync(AuthUserChangePasswordRequest request,
 222        Metadata headers = null, DateTime? deadline = null,
 6223        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6224        .AuthClient
 6225        .UserChangePasswordAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 226
 227    /// <summary>
 228    ///     UserGrant grants a role to a specified user
 229    /// </summary>
 230    /// <param name="request">The request to send to the server.</param>
 231    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 232    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 233    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 234    /// <returns>The response received from the server.</returns>
 235    public AuthUserGrantRoleResponse UserGrantRole(AuthUserGrantRoleRequest request,
 236        Metadata headers = null, DateTime? deadline = null,
 2237        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2238        .UserGrantRole(request, headers, deadline, cancellationToken));
 239
 240    /// <summary>
 241    ///     UserGrantRoleAsync grants a role to a specified user in async
 242    /// </summary>
 243    /// <param name="request">The request to send to the server.</param>
 244    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 245    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 246    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 247    /// <returns>The response received from the server.</returns>
 248    public async Task<AuthUserGrantRoleResponse> UserGrantRoleAsync(AuthUserGrantRoleRequest request,
 249        Metadata headers = null, DateTime? deadline = null,
 60250        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 60251        .AuthClient
 60252        .UserGrantRoleAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 253
 254    /// <summary>
 255    ///     UserRevokeRole revokes a role of specified user
 256    /// </summary>
 257    /// <param name="request">The request to send to the server.</param>
 258    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 259    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 260    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 261    /// <returns>The response received from the server.</returns>
 262    public AuthUserRevokeRoleResponse UserRevokeRole(AuthUserRevokeRoleRequest request,
 263        Metadata headers = null, DateTime? deadline = null,
 2264        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2265        .UserRevokeRole(request, headers, deadline, cancellationToken));
 266
 267    /// <summary>
 268    ///     UserRevokeRoleAsync revokes a role of specified user in async
 269    /// </summary>
 270    /// <param name="request">The request to send to the server.</param>
 271    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 272    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 273    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 274    /// <returns>The response received from the server.</returns>
 275    public async Task<AuthUserRevokeRoleResponse> UserRevokeRoleAsync(AuthUserRevokeRoleRequest request,
 276        Metadata headers = null, DateTime? deadline = null,
 4277        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 4278        .AuthClient
 4279        .UserRevokeRoleAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 280
 281    /// <summary>
 282    ///     RoleAdd adds a new role
 283    /// </summary>
 284    /// <param name="request">The request to send to the server.</param>
 285    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 286    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 287    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 288    /// <returns>The response received from the server.</returns>
 289    public AuthRoleAddResponse RoleAdd(AuthRoleAddRequest request, Metadata headers = null,
 290        DateTime? deadline = null,
 4291        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 4292        .RoleAdd(request, headers, deadline, cancellationToken));
 293
 294    /// <summary>
 295    ///     RoleAddAsync adds a new role in async
 296    /// </summary>
 297    /// <param name="request">The request to send to the server.</param>
 298    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 299    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 300    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 301    /// <returns>The response received from the server.</returns>
 302    public async Task<AuthRoleAddResponse> RoleAddAsync(AuthRoleAddRequest request,
 303        Metadata headers = null, DateTime? deadline = null,
 6304        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6305        .AuthClient
 6306        .RoleAddAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 307
 308    /// <summary>
 309    ///     RoleGet gets detailed role information
 310    /// </summary>
 311    /// <param name="request">The request to send to the server.</param>
 312    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 313    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 314    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 315    /// <returns>The response received from the server.</returns>
 316    public AuthRoleGetResponse RoleGet(AuthRoleGetRequest request, Metadata headers = null,
 317        DateTime? deadline = null,
 2318        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2319        .RoleGet(request, headers, deadline, cancellationToken));
 320
 321    /// <summary>
 322    ///     RoleGetAsync gets detailed role information in async
 323    /// </summary>
 324    /// <param name="request">The request to send to the server.</param>
 325    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 326    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 327    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 328    /// <returns>The response received from the server.</returns>
 329    public async Task<AuthRoleGetResponse> RoleGetAsync(AuthRoleGetRequest request,
 330        Metadata headers = null, DateTime? deadline = null,
 2331        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 2332        .AuthClient
 2333        .RoleGetAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 334
 335    /// <summary>
 336    ///     RoleList gets lists of all roles
 337    /// </summary>
 338    /// <param name="request">The request to send to the server.</param>
 339    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 340    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 341    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 342    /// <returns>The response received from the server.</returns>
 343    public AuthRoleListResponse RoleList(AuthRoleListRequest request, Metadata headers = null,
 344        DateTime? deadline = null,
 2345        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2346        .RoleList(request, headers, deadline, cancellationToken));
 347
 348    /// <summary>
 349    ///     RoleListAsync gets lists of all roles async
 350    /// </summary>
 351    /// <param name="request">The request to send to the server.</param>
 352    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 353    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 354    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 355    /// <returns>The response received from the server.</returns>
 356    public async Task<AuthRoleListResponse> RoleListAsync(AuthRoleListRequest request,
 357        Metadata headers = null, DateTime? deadline = null,
 66358        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 66359        .AuthClient
 66360        .RoleListAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 361
 362    /// <summary>
 363    ///     RoleDelete deletes a specified role
 364    /// </summary>
 365    /// <param name="request">The request to send to the server.</param>
 366    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 367    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 368    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 369    /// <returns>The response received from the server.</returns>
 370    public AuthRoleDeleteResponse RoleDelete(AuthRoleDeleteRequest request, Metadata headers = null,
 371        DateTime? deadline = null,
 2372        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2373        .RoleDelete(request, headers, deadline, cancellationToken));
 374
 375    /// <summary>
 376    ///     RoleDeleteAsync deletes a specified role in async
 377    /// </summary>
 378    /// <param name="request">The request to send to the server.</param>
 379    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 380    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 381    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 382    /// <returns>The response received from the server.</returns>
 383    public async Task<AuthRoleDeleteResponse> RoleDeleteAsync(AuthRoleDeleteRequest request,
 384        Metadata headers = null, DateTime? deadline = null,
 6385        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6386        .AuthClient
 6387        .RoleDeleteAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 388
 389    /// <summary>
 390    ///     RoleGrantPermission grants a permission of a specified key or range to a specified role
 391    /// </summary>
 392    /// <param name="request">The request to send to the server.</param>
 393    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 394    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 395    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 396    /// <returns>The response received from the server.</returns>
 397    public AuthRoleGrantPermissionResponse RoleGrantPermission(AuthRoleGrantPermissionRequest request,
 398        Metadata headers = null, DateTime? deadline = null,
 4399        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 4400        .RoleGrantPermission(request, headers, deadline, cancellationToken));
 401
 402    /// <summary>
 403    ///     RoleGrantPermissionAsync grants a permission of a specified key or range to a specified role in async
 404    /// </summary>
 405    /// <param name="request">The request to send to the server.</param>
 406    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 407    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 408    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 409    /// <returns>The response received from the server.</returns>
 410    public async Task<AuthRoleGrantPermissionResponse> RoleGrantPermissionAsync(
 411        AuthRoleGrantPermissionRequest request, Metadata headers = null, DateTime? deadline = null,
 6412        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6413        .AuthClient
 6414        .RoleGrantPermissionAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 415
 416    /// <summary>
 417    ///     RoleRevokePermission revokes a key or range permission of a specified role
 418    /// </summary>
 419    /// <param name="request">The request to send to the server.</param>
 420    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 421    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 422    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 423    /// <returns>The response received from the server.</returns>
 424    public AuthRoleRevokePermissionResponse RoleRevokePermission(AuthRoleRevokePermissionRequest request,
 425        Metadata headers = null, DateTime? deadline = null,
 2426        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.AuthClient
 2427        .RoleRevokePermission(request, headers, deadline, cancellationToken));
 428
 429    /// <summary>
 430    ///     RoleRevokePermissionAsync revokes a key or range permission of a specified role in async
 431    /// </summary>
 432    /// <param name="request">The request to send to the server.</param>
 433    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 434    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 435    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 436    /// <returns>The response received from the server.</returns>
 437    public async Task<AuthRoleRevokePermissionResponse> RoleRevokePermissionAsync(
 438        AuthRoleRevokePermissionRequest request, Metadata headers = null, DateTime? deadline = null,
 2439        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 2440        .AuthClient
 2441        .RoleRevokePermissionAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 442}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/clusterClient.cs

#LineLine coverage
 1using System;
 2using System.Threading;
 3using System.Threading.Tasks;
 4using Etcdserverpb;
 5using Grpc.Core;
 6
 7namespace dotnet_etcd;
 8
 9public partial class EtcdClient
 10{
 11    /// <summary>
 12    ///     MemberAdd adds a member into the cluster
 13    /// </summary>
 14    /// <param name="request">The request to send to the server.</param>
 15    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 16    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 17    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 18    /// <returns>The response received from the server.</returns>
 19    public MemberAddResponse MemberAdd(MemberAddRequest request, Metadata headers = null,
 20        DateTime? deadline = null,
 221        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.ClusterClient
 222        .MemberAdd(request, headers, deadline, cancellationToken));
 23
 24    /// <summary>
 25    ///     MemberAddAsync adds a member into the cluster in async
 26    /// </summary>
 27    /// <param name="request">The request to send to the server.</param>
 28    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 29    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 30    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 31    /// <returns>The response received from the server.</returns>
 32    public async Task<MemberAddResponse> MemberAddAsync(MemberAddRequest request, Metadata headers = null,
 33        DateTime? deadline = null,
 234        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 235        .ClusterClient
 236        .MemberAddAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 37
 38    /// <summary>
 39    ///     MemberRemove removes an existing member from the cluster
 40    /// </summary>
 41    /// <param name="request">The request to send to the server.</param>
 42    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 43    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 44    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 45    /// <returns>The response received from the server.</returns>
 46    public MemberRemoveResponse MemberRemove(MemberRemoveRequest request, Metadata headers = null,
 47        DateTime? deadline = null,
 248        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.ClusterClient
 249        .MemberRemove(request, headers, deadline, cancellationToken));
 50
 51    /// <summary>
 52    ///     MemberRemoveAsync removes an existing member from the cluster in async
 53    /// </summary>
 54    /// <param name="request">The request to send to the server.</param>
 55    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 56    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 57    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 58    /// <returns>The response received from the server.</returns>
 59    public async Task<MemberRemoveResponse> MemberRemoveAsync(MemberRemoveRequest request,
 60        Metadata headers = null, DateTime? deadline = null,
 261        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 262        .ClusterClient
 263        .MemberRemoveAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 64
 65    /// <summary>
 66    ///     MemberUpdate updates the member configuration
 67    /// </summary>
 68    /// <param name="request">The request to send to the server.</param>
 69    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 70    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 71    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 72    /// <returns>The response received from the server.</returns>
 73    public MemberUpdateResponse MemberUpdate(MemberUpdateRequest request, Metadata headers = null,
 74        DateTime? deadline = null,
 275        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.ClusterClient
 276        .MemberUpdate(request, headers, deadline, cancellationToken));
 77
 78    /// <summary>
 79    ///     MemberUpdateAsync updates the member configuration in async
 80    /// </summary>
 81    /// <param name="request">The request to send to the server.</param>
 82    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 83    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 84    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 85    /// <returns>The response received from the server.</returns>
 86    public async Task<MemberUpdateResponse> MemberUpdateAsync(MemberUpdateRequest request,
 87        Metadata headers = null, DateTime? deadline = null,
 288        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 289        .ClusterClient
 290        .MemberUpdateAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 91
 92    /// <summary>
 93    ///     MemberList lists all the members in the cluster
 94    /// </summary>
 95    /// <param name="request">The request to send to the server.</param>
 96    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 97    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 98    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 99    /// <returns>The response received from the server.</returns>
 100    public MemberListResponse MemberList(MemberListRequest request, Metadata headers = null,
 101        DateTime? deadline = null,
 2102        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.ClusterClient
 2103        .MemberList(request, headers, deadline, cancellationToken));
 104
 105    /// <summary>
 106    ///     MemberListAsync lists all the members in the cluster in async
 107    /// </summary>
 108    /// <param name="request">The request to send to the server.</param>
 109    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 110    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 111    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 112    /// <returns>The response received from the server.</returns>
 113    public async Task<MemberListResponse> MemberListAsync(MemberListRequest request,
 114        Metadata headers = null, DateTime? deadline = null,
 2115        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 2116        .ClusterClient
 2117        .MemberListAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 118}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/electionClient.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Runtime.CompilerServices;
 4using System.Threading;
 5using System.Threading.Tasks;
 6using Google.Protobuf;
 7using Grpc.Core;
 8using V3Electionpb;
 9
 10namespace dotnet_etcd;
 11
 12public partial class EtcdClient
 13{
 14    /// <summary>
 15    ///     Campaign waits to acquire leadership in an election, returning a LeaderKey
 16    ///     representing the leadership if successful. The LeaderKey can then be used
 17    ///     to issue new values on the election, transactionally guard API requests on
 18    ///     leadership still being held, and resign from the election.
 19    /// </summary>
 20    /// <param name="request">The request to send to the server.</param>
 21    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 22    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 23    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 24    /// <returns>The response received from the server.</returns>
 25    public CampaignResponse Campaign(
 26        CampaignRequest request,
 27        Metadata headers = null,
 28        DateTime? deadline = null,
 29        CancellationToken cancellationToken = default)
 1430        => CallEtcd(connection => connection.ElectionClient.Campaign(
 1431            request ?? throw new ArgumentNullException(nameof(request)),
 1432            headers,
 1433            deadline,
 1434            cancellationToken));
 35
 36    /// <summary>
 37    ///     Campaign waits to acquire leadership in an election, returning a LeaderKey
 38    ///     representing the leadership if successful. The LeaderKey can then be used
 39    ///     to issue new values on the election, transactionally guard API requests on
 40    ///     leadership still being held, and resign from the election.
 41    /// </summary>
 42    /// <param name="name">The name is the election�s identifier for the campaign.</param>
 43    /// <param name="value">The value is the initial proclaimed value set when the campaigner wins the election.</param>
 44    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 45    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 46    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 47    /// <returns>The response received from the server.</returns>
 48    public CampaignResponse Campaign(
 49        string name,
 50        string value = null,
 51        Metadata headers = null,
 52        DateTime? deadline = null,
 53        CancellationToken cancellationToken = default)
 254        => CallEtcd(connection => connection.ElectionClient.Campaign(
 255            new CampaignRequest
 256            {
 257                Name = ByteString.CopyFromUtf8(name ?? throw new ArgumentNullException(nameof(name))),
 258                Value = value == null ? null : ByteString.CopyFromUtf8(value)
 259            },
 260            headers,
 261            deadline,
 262            cancellationToken));
 63
 64    /// <summary>
 65    ///     CampaignAsync waits to acquire leadership in an election, returning a LeaderKey
 66    ///     representing the leadership if successful. The LeaderKey can then be used
 67    ///     to issue new values on the election, transactionally guard API requests on
 68    ///     leadership still being held, and resign from the election.
 69    /// </summary>
 70    /// <param name="request">The request to send to the server.</param>
 71    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 72    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 73    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 74    /// <returns>The response received from the server.</returns>
 75    public async Task<CampaignResponse> CampaignAsync(
 76        CampaignRequest request,
 77        Metadata headers = null,
 78        DateTime? deadline = null,
 79        CancellationToken cancellationToken = default)
 1480        => await CallEtcdAsync(async connection => await connection.ElectionClient.CampaignAsync(
 1481            request ?? throw new ArgumentNullException(nameof(request)),
 1482            headers,
 1483            deadline,
 1484            cancellationToken)).ConfigureAwait(false);
 85
 86    /// <summary>
 87    ///     Campaign waits to acquire leadership in an election, returning a LeaderKey
 88    ///     representing the leadership if successful. The LeaderKey can then be used
 89    ///     to issue new values on the election, transactionally guard API requests on
 90    ///     leadership still being held, and resign from the election.
 91    /// </summary>
 92    /// <param name="name">The name is the election�s identifier for the campaign.</param>
 93    /// <param name="value">The value is the initial proclaimed value set when the campaigner wins the election.</param>
 94    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 95    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 96    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 97    /// <returns>The response received from the server.</returns>
 98    public async Task<CampaignResponse> CampaignAsync(
 99        string name,
 100        string value,
 101        Metadata headers = null,
 102        DateTime? deadline = null,
 103        CancellationToken cancellationToken = default)
 2104        => await CallEtcdAsync(async connection => await connection.ElectionClient.CampaignAsync(
 2105            new CampaignRequest
 2106            {
 2107                Name = ByteString.CopyFromUtf8(name ?? throw new ArgumentNullException(nameof(name))),
 2108                Value = value == null ? null : ByteString.CopyFromUtf8(value)
 2109            },
 2110            headers,
 2111            deadline,
 2112            cancellationToken)).ConfigureAwait(false);
 113
 114    /// <summary>
 115    ///     Proclaim updates the leader's posted value with a new value.
 116    /// </summary>
 117    /// <param name="request">The request to send to the server.</param>
 118    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 119    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 120    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 121    /// <returns>The response received from the server.</returns>
 122    public ProclaimResponse Proclaim(
 123        ProclaimRequest request,
 124        Metadata headers = null,
 125        DateTime? deadline = null,
 126        CancellationToken cancellationToken = default)
 6127        => CallEtcd(connection => connection.ElectionClient.Proclaim(
 6128            request ?? throw new ArgumentNullException(nameof(request)),
 6129            headers,
 6130            deadline,
 6131            cancellationToken));
 132
 133    /// <summary>
 134    ///     Proclaim updates the leader's posted value with a new value.
 135    /// </summary>
 136    /// <param name="leader">The leader is the leadership hold on the election.</param>
 137    /// <param name="value">The value is an update meant to overwrite the leader�s current value.</param>
 138    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 139    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 140    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 141    /// <returns>The response received from the server.</returns>
 142    public ProclaimResponse Proclaim(
 143        LeaderKey leader,
 144        string value,
 145        Metadata headers = null,
 146        DateTime? deadline = null,
 147        CancellationToken cancellationToken = default)
 2148        => CallEtcd(connection => connection.ElectionClient.Proclaim(
 2149            new ProclaimRequest
 2150            {
 2151                Leader = leader ?? throw new ArgumentNullException(nameof(leader)),
 2152                Value = ByteString.CopyFromUtf8(value ?? throw new ArgumentNullException(nameof(value)))
 2153            },
 2154            headers,
 2155            deadline,
 2156            cancellationToken));
 157
 158    /// <summary>
 159    ///     Proclaim updates the leader's posted value with a new value.
 160    /// </summary>
 161    /// <param name="request">The request to send to the server.</param>
 162    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 163    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 164    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 165    /// <returns>The response received from the server.</returns>
 166    public async Task<ProclaimResponse> ProclaimAsync(
 167        ProclaimRequest request,
 168        Metadata headers = null,
 169        DateTime? deadline = null,
 170        CancellationToken cancellationToken = default)
 6171        => await CallEtcdAsync(async connection => await connection.ElectionClient.ProclaimAsync(
 6172            request ?? throw new ArgumentNullException(nameof(request)),
 6173            headers,
 6174            deadline,
 6175            cancellationToken)).ConfigureAwait(false);
 176
 177    /// <summary>
 178    ///     Proclaim updates the leader's posted value with a new value.
 179    /// </summary>
 180    /// <param name="leader">The leader is the leadership hold on the election.</param>
 181    /// <param name="value">The value is an update meant to overwrite the leader�s current value.</param>
 182    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 183    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 184    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 185    /// <returns>The response received from the server.</returns>
 186    public async Task<ProclaimResponse> ProclaimAsync(
 187        LeaderKey leader,
 188        string value,
 189        Metadata headers = null,
 190        DateTime? deadline = null,
 191        CancellationToken cancellationToken = default)
 2192        => await CallEtcdAsync(async connection => await connection.ElectionClient.ProclaimAsync(
 2193            new ProclaimRequest
 2194            {
 2195                Leader = leader ?? throw new ArgumentNullException(nameof(leader)),
 2196                Value = ByteString.CopyFromUtf8(value ?? throw new ArgumentNullException(nameof(value)))
 2197            },
 2198            headers,
 2199            deadline,
 2200            cancellationToken)).ConfigureAwait(false);
 201
 202    /// <summary>
 203    ///     Leader returns the current election proclamation, if any.
 204    /// </summary>
 205    /// <param name="request">The request to send to the server.</param>
 206    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 207    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 208    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 209    /// <returns>The response received from the server.</returns>
 210    public LeaderResponse Leader(
 211        LeaderRequest request,
 212        Metadata headers = null,
 213        DateTime? deadline = null,
 214        CancellationToken cancellationToken = default)
 6215        => CallEtcd(connection => connection.ElectionClient.Leader(
 6216            request ?? throw new ArgumentNullException(nameof(request)),
 6217            headers,
 6218            deadline,
 6219            cancellationToken));
 220
 221    /// <summary>
 222    ///     Leader returns the current election proclamation, if any.
 223    /// </summary>
 224    /// <param name="name">The name is the election identifier for the leadership information.</param>
 225    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 226    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 227    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 228    /// <returns>The response received from the server.</returns>
 229    public LeaderResponse Leader(
 230        string name,
 231        Metadata headers = null,
 232        DateTime? deadline = null,
 233        CancellationToken cancellationToken = default)
 6234        => CallEtcd(connection => connection.ElectionClient.Leader(
 6235            new LeaderRequest { Name = ByteString.CopyFromUtf8(name ?? throw new ArgumentNullException(nameof(name))) },
 6236            headers,
 6237            deadline,
 6238            cancellationToken));
 239
 240    /// <summary>
 241    ///     Leader returns the current election proclamation, if any.
 242    /// </summary>
 243    /// <param name="request">The request to send to the server.</param>
 244    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 245    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 246    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 247    /// <returns>The response received from the server.</returns>
 248    public async Task<LeaderResponse> LeaderAsync(
 249        LeaderRequest request,
 250        Metadata headers = null,
 251        DateTime? deadline = null,
 252        CancellationToken cancellationToken = default)
 6253        => await CallEtcdAsync(async connection => await connection.ElectionClient.LeaderAsync(
 6254            request ?? throw new ArgumentNullException(nameof(request)),
 6255            headers,
 6256            deadline,
 6257            cancellationToken)).ConfigureAwait(false);
 258
 259    /// <summary>
 260    ///     Leader returns the current election proclamation, if any.
 261    /// </summary>
 262    /// <param name="name">The name is the election identifier for the leadership information.</param>
 263    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 264    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 265    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 266    /// <returns>The response received from the server.</returns>
 267    public async Task<LeaderResponse> LeaderAsync(
 268        string name,
 269        Metadata headers = null,
 270        DateTime? deadline = null,
 271        CancellationToken cancellationToken = default)
 6272        => await CallEtcdAsync(async connection => await connection.ElectionClient.LeaderAsync(
 6273            new LeaderRequest { Name = ByteString.CopyFromUtf8(name ?? throw new ArgumentNullException(nameof(name))) },
 6274            headers,
 6275            deadline,
 6276            cancellationToken)).ConfigureAwait(false);
 277
 278    /// <summary>
 279    ///     Observe streams election proclamations in-order as made by the election's
 280    ///     elected leaders.
 281    /// </summary>
 282    /// <param name="request">The request to send to the server.</param>
 283    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 284    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 285    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 286    /// <returns>The response received from the server.</returns>
 287    public async IAsyncEnumerable<LeaderResponse> ObserveAsync(
 288        LeaderRequest request,
 289        Metadata headers = null,
 290        DateTime? deadline = null,
 291        [EnumeratorCancellation] CancellationToken cancellationToken = default)
 2292    {
 2293        using (AsyncServerStreamingCall<LeaderResponse> leaderResponse = _connection.ElectionClient.Observe(
 2294                   request ?? throw new ArgumentNullException(nameof(request)),
 2295                   headers,
 2296                   deadline,
 2297                   cancellationToken))
 1298        {
 4299            while (await leaderResponse.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 3300            {
 3301                yield return leaderResponse.ResponseStream.Current;
 3302            }
 1303        }
 1304    }
 305
 306    /// <summary>
 307    ///     Observe streams election proclamations in-order as made by the election's
 308    ///     elected leaders.
 309    /// </summary>
 310    /// <param name="name">The name is the election identifier for the leadership information.</param>
 311    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 312    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 313    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 314    /// <returns>The response received from the server.</returns>
 315    public async IAsyncEnumerable<LeaderResponse> ObserveAsync(
 316        string name,
 317        Metadata headers = null,
 318        DateTime? deadline = null,
 319        [EnumeratorCancellation] CancellationToken cancellationToken = default)
 2320    {
 2321        using (AsyncServerStreamingCall<LeaderResponse> leaderResponse = _connection.ElectionClient.Observe(
 2322                   new LeaderRequest
 2323                   {
 2324                       Name = ByteString.CopyFromUtf8(name ?? throw new ArgumentNullException(nameof(name)))
 2325                   },
 2326                   headers,
 2327                   deadline,
 2328                   cancellationToken))
 1329        {
 2330            while (await leaderResponse.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 1331            {
 1332                yield return leaderResponse.ResponseStream.Current;
 1333            }
 1334        }
 1335    }
 336
 337    /// <summary>
 338    ///     Resign releases election leadership so other campaigners may acquire
 339    ///     leadership on the election.
 340    /// </summary>
 341    /// <param name="request">The request to send to the server.</param>
 342    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 343    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 344    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 345    /// <returns>The response received from the server.</returns>
 346    public ResignResponse Resign(
 347        ResignRequest request,
 348        Metadata headers = null,
 349        DateTime? deadline = null,
 350        CancellationToken cancellationToken = default)
 14351        => CallEtcd(connection => connection.ElectionClient.Resign(
 14352            request ?? throw new ArgumentNullException(nameof(request)),
 14353            headers,
 14354            deadline,
 14355            cancellationToken));
 356
 357    /// <summary>
 358    ///     Resign releases election leadership so other campaigners may acquire
 359    ///     leadership on the election.
 360    /// </summary>
 361    /// <param name="leader">The leader is the leadership to relinquish by resignation.</param>
 362    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 363    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 364    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 365    /// <returns>The response received from the server.</returns>
 366    public ResignResponse Resign(
 367        LeaderKey leader,
 368        Metadata headers = null,
 369        DateTime? deadline = null,
 370        CancellationToken cancellationToken = default)
 2371        => CallEtcd(connection => connection.ElectionClient.Resign(
 2372            new ResignRequest { Leader = leader ?? throw new ArgumentNullException(nameof(leader)) },
 2373            headers,
 2374            deadline,
 2375            cancellationToken));
 376
 377    /// <summary>
 378    ///     Resign releases election leadership so other campaigners may acquire
 379    ///     leadership on the election.
 380    /// </summary>
 381    /// <param name="request">The request to send to the server.</param>
 382    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 383    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 384    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 385    /// <returns>The response received from the server.</returns>
 386    public async Task<ResignResponse> ResignAsync(
 387        ResignRequest request,
 388        Metadata headers = null,
 389        DateTime? deadline = null,
 390        CancellationToken cancellationToken = default)
 14391        => await CallEtcdAsync(async connection => await connection.ElectionClient.ResignAsync(
 14392            request ?? throw new ArgumentNullException(nameof(request)),
 14393            headers,
 14394            deadline,
 14395            cancellationToken)).ConfigureAwait(false);
 396
 397    /// <summary>
 398    ///     Resign releases election leadership so other campaigners may acquire
 399    ///     leadership on the election.
 400    /// </summary>
 401    /// <param name="leader">The leader is the leadership to relinquish by resignation.</param>
 402    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 403    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 404    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 405    /// <returns>The response received from the server.</returns>
 406    public async Task<ResignResponse> ResignAsync(
 407        LeaderKey leader,
 408        Metadata headers = null,
 409        DateTime? deadline = null,
 410        CancellationToken cancellationToken = default)
 2411        => await CallEtcdAsync(async connection => await connection.ElectionClient.ResignAsync(
 2412            new ResignRequest { Leader = leader ?? throw new ArgumentNullException(nameof(leader)) },
 2413            headers,
 2414            deadline,
 2415            cancellationToken)).ConfigureAwait(false);
 416
 417    /// <summary>
 418    ///     Observe streams election proclamations in-order as made by the election's
 419    ///     elected leaders.
 420    /// </summary>
 421    /// <param name="request">The request to send to the server.</param>
 422    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 423    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 424    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 425    /// <returns>The response received from the server.</returns>
 426    public AsyncServerStreamingCall<LeaderResponse> Observe(
 427        LeaderRequest request,
 428        Metadata headers = null,
 429        DateTime? deadline = null,
 430        CancellationToken cancellationToken = default)
 4431        => CallEtcd(connection => connection.ElectionClient.Observe(
 4432            request ?? throw new ArgumentNullException(nameof(request)),
 4433            headers,
 4434            deadline,
 4435            cancellationToken));
 436
 437    /// <summary>
 438    ///     Observe streams election proclamations in-order as made by the election's
 439    ///     elected leaders.
 440    /// </summary>
 441    /// <param name="name">The name is the election identifier for the leadership information.</param>
 442    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 443    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 444    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 445    /// <returns>The response received from the server.</returns>
 446    public AsyncServerStreamingCall<LeaderResponse> Observe(
 447        string name,
 448        Metadata headers = null,
 449        DateTime? deadline = null,
 450        CancellationToken cancellationToken = default)
 4451        => CallEtcd(connection => connection.ElectionClient.Observe(
 4452            new LeaderRequest { Name = ByteString.CopyFromUtf8(name ?? throw new ArgumentNullException(nameof(name))) },
 4453            headers,
 4454            deadline,
 4455            cancellationToken));
 456}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/etcdClient.cs

#LineLine coverage
 1using System;
 2using System.Net.Security;
 3using System.Threading;
 4using System.Threading.Tasks;
 5using dotnet_etcd.interfaces;
 6using dotnet_etcd.multiplexer;
 7using Etcdserverpb;
 8using Grpc.Core;
 9using Grpc.Core.Interceptors;
 10using Grpc.Net.Client;
 11using Grpc.Net.Client.Configuration;
 12
 13namespace dotnet_etcd;
 14
 15/// <summary>
 16///     Etcd client is the entrypoint for this library.
 17///     It contains all the functions required to perform operations on etcd.
 18/// </summary>
 19public partial class EtcdClient : IDisposable, IEtcdClient
 20{
 21    /// <summary>
 22    ///     Gets the connection object
 23    /// </summary>
 24    /// <returns>The connection object</returns>
 125    public IConnection GetConnection() => _connection;
 26
 27    /// <summary>
 28    ///     Gets the watch manager
 29    /// </summary>
 30    /// <returns>The watch manager</returns>
 131    public IWatchManager GetWatchManager() => _watchManager;
 32
 33    /// <summary>
 34    ///     Cancels a watch request
 35    /// </summary>
 36    /// <param name="watchId">The ID of the watch to cancel</param>
 137    public void CancelWatch(long watchId) => _watchManager.CancelWatch(watchId);
 38
 39    /// <summary>
 40    ///     Cancels multiple watch requests
 41    /// </summary>
 42    /// <param name="watchIds">The IDs of the watches to cancel</param>
 43    public void CancelWatch(long[] watchIds)
 244    {
 1245        foreach (long watchId in watchIds)
 346        {
 347            _watchManager.CancelWatch(watchId);
 348        }
 249    }
 50
 51    #region Variables
 52
 53    private const string InsecurePrefix = "http://";
 54    private const string SecurePrefix = "https://";
 55
 56    private const string StaticHostsPrefix = "static://";
 57    private const string DnsPrefix = "dns://";
 58    private const string AlternateDnsPrefix = "discovery-srv://";
 59
 60    private const string DefaultServerName = "my-etcd-server";
 61
 62    internal readonly IConnection _connection;
 63    private readonly GrpcChannel _channel;
 64    private readonly IWatchManager _watchManager;
 65    private readonly AsyncStreamCallFactory<WatchRequest, WatchResponse> _watchCallFactory;
 66
 17267    private sealed record EtcdCredentials(string Username, string Password);
 68
 69    private volatile EtcdCredentials _credentials;
 70    private AuthenticationHttpHandler _authHttpHandler;
 71
 72    // ETCD Tokens are valid for 5 min per default, so we cache them for the 5 min - 1 min safety margin.
 34673    private TimeSpan _tokenCacheDuration = TimeSpan.FromMinutes(4);
 74
 75    // https://learn.microsoft.com/en-us/aspnet/core/grpc/retries?view=aspnetcore-6.0#configure-a-grpc-retry-policy
 176    private static readonly MethodConfig _defaultGrpcMethodConfig = new()
 177    {
 178        Names = { MethodName.Default },
 179        RetryPolicy = new RetryPolicy
 180        {
 181            MaxAttempts = 5,
 182            InitialBackoff = TimeSpan.FromSeconds(1),
 183            MaxBackoff = TimeSpan.FromSeconds(5),
 184            BackoffMultiplier = 1.5,
 185            RetryableStatusCodes = { StatusCode.Unavailable },
 186        },
 187    };
 88
 89    // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#throttling-retry-attempts-and-hedged-rpcs
 190    private static readonly RetryThrottlingPolicy _defaultRetryThrottlingPolicy = new()
 191    {
 192        MaxTokens = 10,
 193        TokenRatio = 0.1,
 194    };
 95
 96    #endregion
 97
 98    #region Initializers
 99
 100    /// <summary>
 101    ///     Initializes a new instance of the <see cref="EtcdClient" /> class with a CallInvoker.
 102    ///     Automatic authentication is not configured for this overload â€” the caller is responsible
 103    ///     for attaching any auth credentials to the supplied CallInvoker.
 104    /// </summary>
 105    /// <param name="callInvoker">The call invoker to use for gRPC calls</param>
 106    /// <exception cref="ArgumentNullException">Thrown if callInvoker is null</exception>
 200107    public EtcdClient(CallInvoker callInvoker)
 200108    {
 200109        ArgumentNullException.ThrowIfNull(callInvoker);
 110
 199111        _connection = new Connection(callInvoker);
 112
 113        // Create the watch call factory
 199114        _watchCallFactory = new AsyncStreamCallFactory<WatchRequest, WatchResponse>(
 199115            (headers, deadline, cancellationToken) =>
 0116                _connection.WatchClient.Watch(headers, deadline, cancellationToken)
 199117        );
 118
 119        // Initialize the watch manager
 199120        _watchManager = new WatchManager(
 199121            (headers, deadline, cancellationToken) =>
 0122                _watchCallFactory.CreateDuplexStreamingCall(headers, deadline, cancellationToken)
 199123        );
 199124    }
 125
 126    /// <summary>
 127    ///     Initializes a new instance of the <see cref="EtcdClient" /> class with a connection string.
 128    /// </summary>
 129    /// <param name="connectionString">The connection string for etcd</param>
 130    /// <param name="port">The port to connect to</param>
 131    /// <param name="serverName">The server name</param>
 132    /// <param name="configureChannelOptions">Function to configure channel options</param>
 133    /// <param name="interceptors">Interceptors to apply to calls</param>
 134    /// <exception cref="ArgumentNullException">Thrown if connectionString is null or empty</exception>
 104135    public EtcdClient(
 104136        string connectionString,
 104137        int port = 2379,
 104138        string serverName = DefaultServerName,
 104139        Action<GrpcChannelOptions> configureChannelOptions = null,
 104140        Interceptor[] interceptors = null
 104141    )
 104142    {
 143        // Param check
 104144        if (string.IsNullOrWhiteSpace(connectionString))
 3145        {
 3146            throw new ArgumentNullException(nameof(connectionString));
 147        }
 148
 149        // Param sanitization
 101150        interceptors ??= Array.Empty<Interceptor>();
 151
 101152        var channelFactory = new GrpcChannelFactory();
 101153        _channel = channelFactory.CreateChannel(
 101154            connectionString,
 101155            port,
 101156            serverName,
 101157            ChannelCredentials.Insecure, // Default to insecure for backward compatibility
 101158            options =>
 101159            {
 101160                configureChannelOptions?.Invoke(options);
 101161                _authHttpHandler = new AuthenticationHttpHandler(
 101162                    RequestTokenAsync,
 101163                    options.HttpHandler!
 101164                );
 101165                options.HttpHandler = _authHttpHandler;
 101166            },
 101167            configureSslOptions: null // No custom SSL by default
 101168        );
 169
 101170        CallInvoker callInvoker =
 101171            interceptors.Length > 0
 101172                ? _channel.Intercept(interceptors)
 101173                : _channel.CreateCallInvoker();
 174
 175        // Setup Connection
 101176        _connection = new Connection(callInvoker);
 177
 178        // Create the watch call factory
 101179        _watchCallFactory = new AsyncStreamCallFactory<WatchRequest, WatchResponse>(
 101180            (headers, deadline, cancellationToken) =>
 9181                _connection.WatchClient.Watch(headers, deadline, cancellationToken)
 101182        );
 183
 184        // Initialize the watch manager
 101185        _watchManager = new WatchManager(
 101186            (headers, deadline, cancellationToken) =>
 9187                _watchCallFactory.CreateDuplexStreamingCall(headers, deadline, cancellationToken)
 101188        );
 101189    }
 190
 191    /// <summary>
 192    ///     Initializes a new instance of the <see cref="EtcdClient" /> class with a connection string and SSL options c
 193    ///     Use this constructor to configure custom SSL certificates for self-signed certificates.
 194    /// </summary>
 195    /// <param name="connectionString">The connection string for etcd</param>
 196    /// <param name="configureSslOptions">Action to configure SSL options for custom SSL certificates</param>
 197    /// <param name="port">The port to connect to</param>
 198    /// <param name="serverName">The server name</param>
 199    /// <param name="configureChannelOptions">Function to configure channel options</param>
 200    /// <param name="interceptors">Interceptors to apply to calls</param>
 201    /// <exception cref="ArgumentNullException">Thrown if connectionString is null or empty</exception>
 3202    public EtcdClient(
 3203        string connectionString,
 3204        Action<SslClientAuthenticationOptions> configureSslOptions,
 3205        int port = 2379,
 3206        string serverName = DefaultServerName,
 3207        Action<GrpcChannelOptions> configureChannelOptions = null,
 3208        Interceptor[] interceptors = null
 3209    )
 3210    {
 211        // Param check
 3212        if (string.IsNullOrWhiteSpace(connectionString))
 0213        {
 0214            throw new ArgumentNullException(nameof(connectionString));
 215        }
 216
 217        // Param sanitization
 3218        interceptors ??= Array.Empty<Interceptor>();
 219
 3220        var channelFactory = new GrpcChannelFactory();
 221
 222        // Use SSL credentials when SSL options configuration is provided
 3223        var credentials =
 3224            configureSslOptions != null ? new SslCredentials() : ChannelCredentials.Insecure;
 225
 3226        _channel = channelFactory.CreateChannel(
 3227            connectionString,
 3228            port,
 3229            serverName,
 3230            credentials,
 3231            options =>
 3232            {
 3233                configureChannelOptions?.Invoke(options);
 3234                _authHttpHandler = new AuthenticationHttpHandler(
 3235                    RequestTokenAsync,
 3236                    options.HttpHandler!
 3237                );
 3238                options.HttpHandler = _authHttpHandler;
 3239            },
 3240            configureSslOptions
 3241        );
 3242        CallInvoker callInvoker =
 3243            interceptors.Length > 0
 3244                ? _channel.Intercept(interceptors)
 3245                : _channel.CreateCallInvoker();
 246
 247        // Setup Connection
 3248        _connection = new Connection(callInvoker);
 249
 250        // Create the watch call factory
 3251        _watchCallFactory = new AsyncStreamCallFactory<WatchRequest, WatchResponse>(
 3252            (headers, deadline, cancellationToken) =>
 0253                _connection.WatchClient.Watch(headers, deadline, cancellationToken)
 3254        );
 255
 256        // Initialize the watch manager
 3257        _watchManager = new WatchManager(
 3258            (headers, deadline, cancellationToken) =>
 0259                _watchCallFactory.CreateDuplexStreamingCall(headers, deadline, cancellationToken)
 3260        );
 3261    }
 262
 263    /// <summary>
 264    ///     Initializes a new instance of the <see cref="EtcdClient" /> class with a connection string and credentials.
 265    /// </summary>
 266    /// <param name="connectionString">The connection string for etcd</param>
 267    /// <param name="username">The username for authentication</param>
 268    /// <param name="password">The password for authentication</param>
 269    /// <param name="port">The port to connect to</param>
 270    /// <param name="serverName">The server name</param>
 271    /// <param name="configureChannelOptions">Function to configure channel options</param>
 272    /// <param name="tokenCacheDuration">The duration to cache requested tokens from etcd</param>
 273    /// <exception cref="ArgumentNullException">Thrown if connectionString is null or empty</exception>
 274    public EtcdClient(
 275        string connectionString,
 276        string username,
 277        string password,
 278        int port = 2379,
 279        string serverName = DefaultServerName,
 280        Action<GrpcChannelOptions> configureChannelOptions = null,
 281        TimeSpan? tokenCacheDuration = null
 282    )
 15283        : this(connectionString, port, serverName, configureChannelOptions)
 15284    {
 285        // Validate and set credentials
 15286        if (string.IsNullOrWhiteSpace(username))
 3287        {
 3288            throw new ArgumentNullException(nameof(username));
 289        }
 290
 12291        if (string.IsNullOrWhiteSpace(password))
 3292        {
 3293            throw new ArgumentNullException(nameof(password));
 294        }
 295
 9296        if (tokenCacheDuration.HasValue)
 2297            _tokenCacheDuration = tokenCacheDuration.Value;
 298
 9299        _credentials = new EtcdCredentials(username, password);
 9300    }
 301
 302    /// <summary>
 303    ///     Initializes a new instance of the <see cref="EtcdClient" /> class for testing.
 304    /// </summary>
 305    /// <param name="connection">The connection to use</param>
 306    /// <param name="watchManager">The watch manager to use</param>
 307    /// <exception cref="ArgumentNullException">Thrown if connection or watchManager is null</exception>
 39308    public EtcdClient(IConnection connection, IWatchManager watchManager = null)
 39309    {
 39310        ArgumentNullException.ThrowIfNull(connection);
 311
 38312        _connection = connection;
 313
 38314        if (watchManager != null)
 38315        {
 38316            _watchManager = watchManager;
 38317        }
 318        else
 0319        {
 320            // Create the watch call factory
 0321            _watchCallFactory = new AsyncStreamCallFactory<WatchRequest, WatchResponse>(
 0322                (headers, deadline, cancellationToken) =>
 0323                    _connection.WatchClient.Watch(headers, deadline, cancellationToken)
 0324            );
 325
 326            // Initialize the watch manager with default implementation
 0327            _watchManager = new WatchManager(
 0328                (headers, deadline, cancellationToken) =>
 0329                    _watchCallFactory.CreateDuplexStreamingCall(
 0330                        headers,
 0331                        deadline,
 0332                        cancellationToken
 0333                    )
 0334            );
 0335        }
 38336    }
 337
 338    #endregion
 339
 340    #region Authentication
 341
 342    /// <summary>
 343    ///     Sets the credentials for automatic authentication with etcd.
 344    ///     When credentials are set, all subsequent requests will automatically include the authentication token.
 345    /// </summary>
 346    /// <param name="username">The username for authentication</param>
 347    /// <param name="password">The password for authentication</param>
 348    /// <param name="tokenCacheDuration">The duration to cache requested tokens from etcd</param>
 349    /// <exception cref="ArgumentNullException">Thrown if username or password is null or empty</exception>
 350    /// <exception cref="InvalidOperationException">
 351    ///     Thrown when the client was created from a <see cref="CallInvoker" />, which has no
 352    ///     channel for the library to attach authentication to. Supply credentials on that path
 353    ///     yourself via the CallInvoker.
 354    /// </exception>
 355    public void SetCredentials(
 356        string username,
 357        string password,
 358        TimeSpan? tokenCacheDuration = null
 359    )
 50360    {
 50361        if (string.IsNullOrWhiteSpace(username))
 0362        {
 0363            throw new ArgumentNullException(nameof(username));
 364        }
 365
 50366        if (string.IsNullOrWhiteSpace(password))
 0367        {
 0368            throw new ArgumentNullException(nameof(password));
 369        }
 370
 50371        EnsureAuthenticationSupported();
 372
 49373        if (tokenCacheDuration.HasValue)
 0374            _tokenCacheDuration = tokenCacheDuration.Value;
 375
 49376        _credentials = new EtcdCredentials(username, password);
 377
 378        // Purge any token cached under the previous credentials so the next request re-auths.
 49379        _authHttpHandler.InvalidateToken();
 49380    }
 381
 382    /// <summary>
 383    ///     Clears the current credentials if set and invalidates any cached token.
 384    /// </summary>
 385    /// <exception cref="InvalidOperationException">
 386    ///     Thrown when the client was created from a <see cref="CallInvoker" /> and therefore
 387    ///     does not manage authentication.
 388    /// </exception>
 389    public void ClearCredentials()
 17390    {
 17391        EnsureAuthenticationSupported();
 392
 16393        _credentials = null;
 16394        _authHttpHandler.InvalidateToken();
 16395    }
 396
 397    /// <summary>
 398    ///     Guards the credential APIs against the CallInvoker overload, where no channel â€” and thus
 399    ///     no <see cref="AuthenticationHttpHandler" /> â€” exists to carry the auth token. Failing
 400    ///     here turns a silent no-op (requests going out unauthenticated) into an explicit error.
 401    /// </summary>
 402    private void EnsureAuthenticationSupported()
 67403    {
 67404        if (_authHttpHandler is null)
 2405        {
 2406            throw new InvalidOperationException(
 2407                "This EtcdClient was created from a CallInvoker, which the library cannot attach "
 2408                    + "authentication to. Construct the client with a connection string to use "
 2409                    + "SetCredentials/ClearCredentials, or attach credentials to the CallInvoker yourself."
 2410            );
 411        }
 65412    }
 413
 414    private async Task<(string token, TimeSpan cacheDuration)?> RequestTokenAsync(
 415        CancellationToken cancellationToken
 416    )
 135417    {
 135418        EtcdCredentials cred = _credentials;
 135419        if (cred is null)
 78420            return null;
 421
 57422        AuthenticateResponse response = await _connection
 57423            .AuthClient.AuthenticateAsync(
 57424                new AuthenticateRequest
 57425                {
 57426                    Name = cred.Username,
 57427                    Password = cred.Password,
 57428                },
 57429                cancellationToken: cancellationToken
 57430            )
 57431            .ConfigureAwait(false);
 432
 41433        return (response.Token, _tokenCacheDuration);
 119434    }
 435
 436    #endregion
 437
 438    #region IDisposable Support
 439
 440    private bool _disposed;
 441
 442    /// <summary>
 443    ///     Disposes the resources used by this instance
 444    /// </summary>
 445    /// <param name="disposing">Whether to dispose managed resources</param>
 446    protected virtual void Dispose(bool disposing)
 104447    {
 104448        if (!_disposed)
 84449        {
 84450            if (disposing)
 84451            {
 452                // Dispose managed resources
 84453                _channel?.Dispose();
 84454                _watchManager?.Dispose();
 84455            }
 456
 84457            _disposed = true;
 84458        }
 104459    }
 460
 461    /// <summary>
 462    ///     Disposes the resources used by this instance
 463    /// </summary>
 464    public void Dispose()
 104465    {
 104466        Dispose(true);
 104467        GC.SuppressFinalize(this);
 104468    }
 469
 470    #endregion
 471}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/kvClient.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Threading;
 4using System.Threading.Tasks;
 5using Etcdserverpb;
 6using Google.Protobuf;
 7using Grpc.Core;
 8
 9namespace dotnet_etcd;
 10
 11public partial class EtcdClient
 12{
 13    /// <summary>
 14    ///     Get the etcd response for a specified RangeRequest
 15    /// </summary>
 16    /// <param name="request">The request to send to the server.</param>
 17    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 18    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 19    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 20    /// <returns>The etcd response for the specified request</returns>
 21    public RangeResponse Get(RangeRequest request, Metadata headers = null, DateTime? deadline = null,
 3222        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.KVClient
 3223        .Range(request, headers, deadline, cancellationToken));
 24
 25    /// <summary>
 26    ///     Get the etcd response for a specified key
 27    /// </summary>
 28    /// <param name="key">Key for which value need to be fetched</param>
 29    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 30    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 31    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 32    /// <returns>The etcd response for the specified key</returns>
 33    public RangeResponse Get(string key, Metadata headers = null, DateTime? deadline = null,
 834        CancellationToken cancellationToken = default) => Get(new RangeRequest { Key = ByteString.CopyFromUtf8(key) },
 835        headers, deadline, cancellationToken);
 36
 37    /// <summary>
 38    ///     Get the etcd response for a specified key in async
 39    /// </summary>
 40    /// <param name="request">The request to send to the server.</param>
 41    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 42    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 43    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 44    /// <returns>The etcd response for the specified request</returns>
 45    public async Task<RangeResponse> GetAsync(RangeRequest request, Metadata headers = null,
 46        DateTime? deadline = null,
 6447        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6448        .KVClient
 6449        .RangeAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 50
 51    /// <summary>
 52    ///     Get the etcd response for a specified key in async
 53    /// </summary>
 54    /// <param name="key">Key for which value need to be fetched</param>
 55    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 56    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 57    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 58    /// <returns>The etcd response for the specified key</returns>
 59    public async Task<RangeResponse> GetAsync(string key, Metadata headers = null,
 60        DateTime? deadline = null,
 61        CancellationToken cancellationToken = default) =>
 2362        await GetAsync(new RangeRequest { Key = ByteString.CopyFromUtf8(key) }, headers, deadline, cancellationToken)
 2363            .ConfigureAwait(false);
 64
 65    /// <summary>
 66    ///     Get the value for a specified key
 67    /// </summary>
 68    /// <param name="key">Key for which value need to be fetched</param>
 69    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 70    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 71    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 72    /// <returns>The value for the specified key</returns>
 73    public string GetVal(string key, Metadata headers = null, DateTime? deadline = null,
 74        CancellationToken cancellationToken = default)
 475    {
 476        RangeResponse rangeResponse = Get(key, headers, deadline, cancellationToken);
 477        return rangeResponse.Count != 0 ? rangeResponse.Kvs[0].Value.ToStringUtf8().Trim() : string.Empty;
 478    }
 79
 80    /// <summary>
 81    ///     Get the value for a specified key in async
 82    /// </summary>
 83    /// <param name="key">Key for which value need to be fetched</param>
 84    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 85    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 86    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 87    /// <returns>The value for the specified key</returns>
 88    public async Task<string> GetValAsync(string key, Metadata headers = null, DateTime? deadline = null,
 89        CancellationToken cancellationToken = default)
 790    {
 791        RangeResponse rangeResponse = await GetAsync(key, headers, deadline, cancellationToken).ConfigureAwait(false);
 792        return rangeResponse.Count != 0 ? rangeResponse.Kvs[0].Value.ToStringUtf8().Trim() : string.Empty;
 793    }
 94
 95    /// <summary>
 96    ///     Gets the range of keys with the specified prefix
 97    /// </summary>
 98    /// <param name="prefixKey">Prefix key</param>
 99    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 100    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 101    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 102    /// <returns>RangeResponse containing range of key-values</returns>
 103    public RangeResponse GetRange(string prefixKey, Metadata headers = null, DateTime? deadline = null,
 104        CancellationToken cancellationToken = default)
 4105    {
 4106        string rangeEnd = GetRangeEnd(prefixKey);
 4107        return Get(
 4108            new RangeRequest
 4109            {
 4110                Key = GetStringByteForRangeRequests(prefixKey), RangeEnd = ByteString.CopyFromUtf8(rangeEnd)
 4111            }, headers, deadline, cancellationToken);
 4112    }
 113
 114    /// <summary>
 115    ///     Gets the range of keys with the specified prefix in async
 116    /// </summary>
 117    /// <param name="prefixKey">Prefix key</param>
 118    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 119    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 120    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 121    /// <returns>RangeResponse containing range of key-values</returns>
 122    public async Task<RangeResponse> GetRangeAsync(string prefixKey, Metadata headers = null,
 123        DateTime? deadline = null,
 124        CancellationToken cancellationToken = default)
 2125    {
 2126        string rangeEnd = GetRangeEnd(prefixKey);
 2127        return await GetAsync(
 2128            new RangeRequest
 2129            {
 2130                Key = GetStringByteForRangeRequests(prefixKey), RangeEnd = ByteString.CopyFromUtf8(rangeEnd)
 2131            }, headers, deadline, cancellationToken).ConfigureAwait(false);
 2132    }
 133
 134    /// <summary>
 135    ///     Gets the range of keys with the specified prefix
 136    /// </summary>
 137    /// <param name="prefixKey">Prefix key</param>
 138    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 139    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 140    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 141    /// <returns>Dictionary containing range of key-values</returns>
 142    public IDictionary<string, string> GetRangeVal(string prefixKey, Metadata headers = null,
 143        DateTime? deadline = null,
 144        CancellationToken cancellationToken = default)
 2145    {
 2146        string rangeEnd = GetRangeEnd(prefixKey);
 2147        return RangeRespondToDictionary(Get(
 2148            new RangeRequest
 2149            {
 2150                Key = GetStringByteForRangeRequests(prefixKey), RangeEnd = ByteString.CopyFromUtf8(rangeEnd)
 2151            }, headers, deadline, cancellationToken));
 2152    }
 153
 154    /// <summary>
 155    ///     Gets the range of keys with the specified prefix in async
 156    /// </summary>
 157    /// <param name="prefixKey">Prefix key</param>
 158    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 159    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 160    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 161    /// <returns>Dictionary containing range of key-values</returns>
 162    public async Task<IDictionary<string, string>> GetRangeValAsync(string prefixKey,
 163        Metadata headers = null, DateTime? deadline = null,
 164        CancellationToken cancellationToken = default)
 1165    {
 1166        string rangeEnd = GetRangeEnd(prefixKey);
 1167        return RangeRespondToDictionary(
 1168            await GetAsync(
 1169                new RangeRequest
 1170                {
 1171                    Key = GetStringByteForRangeRequests(prefixKey), RangeEnd = ByteString.CopyFromUtf8(rangeEnd)
 1172                }, headers, deadline, cancellationToken).ConfigureAwait(false));
 1173    }
 174
 175    /// <summary>
 176    ///     Sets the key value in etcd
 177    /// </summary>
 178    /// <param name="request">The request to send to the server.</param>
 179    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 180    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 181    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 182    /// <returns>The response received from the server.</returns>
 183    public PutResponse Put(PutRequest request, Metadata headers = null, DateTime? deadline = null,
 19184        CancellationToken cancellationToken = default) => CallEtcd(connection =>
 38185        connection.KVClient.Put(request, headers, deadline, cancellationToken));
 186
 187    /// <summary>
 188    ///     Sets the key value in etcd
 189    /// </summary>
 190    /// <param name="key">Key for which value need to be set</param>
 191    /// <param name="val">Value corresponding the key</param>
 192    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 193    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 194    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 195    /// <returns>The response received from the server.</returns>
 196    public PutResponse Put(string key, string val, Metadata headers = null, DateTime? deadline = null,
 197        CancellationToken cancellationToken = default) =>
 17198        Put(new PutRequest { Key = ByteString.CopyFromUtf8(key), Value = ByteString.CopyFromUtf8(val) }, headers,
 17199            deadline, cancellationToken);
 200
 201    /// <summary>
 202    ///     Sets the key value in etcd in async
 203    /// </summary>
 204    /// <param name="request">The request to send to the server.</param>
 205    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 206    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 207    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 208    /// <returns>The response received from the server.</returns>
 209    public async Task<PutResponse> PutAsync(PutRequest request, Metadata headers = null,
 210        DateTime? deadline = null,
 110211        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 110212        .KVClient
 110213        .PutAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 214
 215
 216    /// <summary>
 217    ///     Sets the key value in etcd in async
 218    /// </summary>
 219    /// <param name="key">Key for which value need to be set</param>
 220    /// <param name="val">Value corresponding the key</param>
 221    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 222    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 223    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 224    /// <returns>The response received from the server.</returns>
 225    public async Task<PutResponse> PutAsync(string key, string val, Metadata headers = null,
 226        DateTime? deadline = null,
 227        CancellationToken cancellationToken = default) =>
 51228        await PutAsync(new PutRequest { Key = ByteString.CopyFromUtf8(key), Value = ByteString.CopyFromUtf8(val) },
 51229            headers, deadline, cancellationToken).ConfigureAwait(false);
 230
 231    /// <summary>
 232    ///     Delete the specified key in etcd
 233    /// </summary>
 234    /// <param name="request">The request to send to the server.</param>
 235    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 236    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 237    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 238    /// <returns>The response received from the server.</returns>
 239    public DeleteRangeResponse Delete(DeleteRangeRequest request, Metadata headers = null,
 240        DateTime? deadline = null,
 32241        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.KVClient
 32242        .DeleteRange(request, headers, deadline, cancellationToken));
 243
 244    /// <summary>
 245    ///     Delete the specified key in etcd
 246    /// </summary>
 247    /// <param name="key">Key which needs to be deleted</param>
 248    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 249    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 250    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 251    /// <returns>The response received from the server.</returns>
 252    public DeleteRangeResponse Delete(string key, Metadata headers = null, DateTime? deadline = null,
 11253        CancellationToken cancellationToken = default) => Delete(
 11254        new DeleteRangeRequest { Key = ByteString.CopyFromUtf8(key) }, headers, deadline, cancellationToken);
 255
 256
 257    /// <summary>
 258    ///     Delete the specified key in etcd in async
 259    /// </summary>
 260    /// <param name="request">The request to send to the server.</param>
 261    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 262    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 263    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 264    /// <returns>The response received from the server.</returns>
 265    public async Task<DeleteRangeResponse> DeleteAsync(DeleteRangeRequest request,
 266        Metadata headers = null, DateTime? deadline = null,
 124267        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 124268        .KVClient
 124269        .DeleteRangeAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 270
 271    /// <summary>
 272    ///     Delete the specified key in etcd in async
 273    /// </summary>
 274    /// <param name="key">Key which needs to be deleted</param>
 275    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 276    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 277    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 278    /// <returns>The response received from the server.</returns>
 279    public async Task<DeleteRangeResponse> DeleteAsync(string key, Metadata headers = null,
 280        DateTime? deadline = null,
 281        CancellationToken cancellationToken = default) =>
 28282        await DeleteAsync(new DeleteRangeRequest { Key = ByteString.CopyFromUtf8(key) }, headers, deadline,
 28283            cancellationToken).ConfigureAwait(false);
 284
 285    /// <summary>
 286    ///     Deletes all keys with the specified prefix
 287    /// </summary>
 288    /// <param name="prefixKey">Common prefix of all keys that need to be deleted</param>
 289    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 290    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 291    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 292    /// <returns>The response received from the server.</returns>
 293    public DeleteRangeResponse DeleteRange(string prefixKey, Metadata headers = null,
 294        DateTime? deadline = null,
 295        CancellationToken cancellationToken = default)
 3296    {
 3297        string rangeEnd = GetRangeEnd(prefixKey);
 3298        return Delete(
 3299            new DeleteRangeRequest
 3300            {
 3301                Key = ByteString.CopyFromUtf8(prefixKey), RangeEnd = ByteString.CopyFromUtf8(rangeEnd)
 3302            }, headers, deadline, cancellationToken);
 3303    }
 304
 305    /// <summary>
 306    ///     Deletes all keys with the specified prefix in async
 307    /// </summary>
 308    /// <param name="prefixKey">Commin prefix of all keys that need to be deleted</param>
 309    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 310    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 311    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 312    /// <returns>The response received from the server.</returns>
 313    public async Task<DeleteRangeResponse> DeleteRangeAsync(string prefixKey, Metadata headers = null,
 314        DateTime? deadline = null,
 315        CancellationToken cancellationToken = default)
 33316    {
 33317        string rangeEnd = GetRangeEnd(prefixKey);
 33318        return await DeleteAsync(
 33319            new DeleteRangeRequest
 33320            {
 33321                Key = ByteString.CopyFromUtf8(prefixKey), RangeEnd = ByteString.CopyFromUtf8(rangeEnd)
 33322            }, headers, deadline, cancellationToken).ConfigureAwait(false);
 33323    }
 324
 325    /// <summary>
 326    ///     Txn processes multiple requests in a single transaction.
 327    ///     A txn request increments the revision of the key-value store
 328    ///     and generates events with the same revision for every completed request.
 329    ///     It is not allowed to modify the same key several times within one txn.
 330    /// </summary>
 331    /// <param name="request">The request to send to the server.</param>
 332    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 333    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 334    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 335    /// <returns>The response received from the server.</returns>
 336    public TxnResponse Transaction(TxnRequest request, Metadata headers = null, DateTime? deadline = null,
 2337        CancellationToken cancellationToken = default) => CallEtcd(connection =>
 4338        connection.KVClient.Txn(request, headers, deadline, cancellationToken));
 339
 340    /// <summary>
 341    ///     Txn processes multiple requests in a single transaction in async.
 342    ///     A txn request increments the revision of the key-value store
 343    ///     and generates events with the same revision for every completed request.
 344    ///     It is not allowed to modify the same key several times within one txn.
 345    /// </summary>
 346    /// <param name="request">The request to send to the server.</param>
 347    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 348    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 349    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 350    /// <returns>The response received from the server.</returns>
 351    public async Task<TxnResponse> TransactionAsync(TxnRequest request, Metadata headers = null,
 352        DateTime? deadline = null,
 6353        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6354        .KVClient
 6355        .TxnAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 356
 357    /// <summary>
 358    ///     Compact compacts the event history in the etcd key-value store. The key-value
 359    ///     store should be periodically compacted or the event history will continue to grow
 360    ///     indefinitely.
 361    /// </summary>
 362    /// <param name="request">The request to send to the server.</param>
 363    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 364    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 365    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 366    /// <returns>The response received from the server.</returns>
 367    public CompactionResponse Compact(CompactionRequest request, Metadata headers = null,
 368        DateTime? deadline = null,
 2369        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.KVClient
 2370        .Compact(request, headers, deadline, cancellationToken));
 371
 372    /// <summary>
 373    ///     Compact compacts the event history in the etcd key-value store in async. The key-value
 374    ///     store should be periodically compacted or the event history will continue to grow
 375    ///     indefinitely.
 376    /// </summary>
 377    /// <param name="request">The request to send to the server.</param>
 378    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 379    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 380    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 381    /// <returns>The response received from the server.</returns>
 382    public async Task<CompactionResponse> CompactAsync(CompactionRequest request, Metadata headers = null,
 383        DateTime? deadline = null,
 2384        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 2385        .KVClient
 2386        .CompactAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 387}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/leaseClient.cs

#LineLine coverage
 1using System;
 2using System.IO;
 3using System.Threading;
 4using System.Threading.Tasks;
 5using dotnet_etcd.interfaces;
 6using Etcdserverpb;
 7using Grpc.Core;
 8
 9namespace dotnet_etcd;
 10
 11public partial class EtcdClient
 12{
 13    /// <summary>
 14    ///     LeaseGrant creates a lease which expires if the server does not receive a keepAlive
 15    ///     within a given time to live period. All keys attached to the lease will be expired and
 16    ///     deleted if the lease expires. Each expired key generates a delete event in the event history.
 17    /// </summary>
 18    /// <param name="request">The request to send to the server.</param>
 19    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 20    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 21    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 22    /// <returns>The response received from the server.</returns>
 23    public LeaseGrantResponse LeaseGrant(LeaseGrantRequest request, Metadata headers = null,
 24        DateTime? deadline = null,
 2225        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.LeaseClient
 2226        .LeaseGrant(request, headers, deadline, cancellationToken));
 27
 28    /// <summary>
 29    ///     LeaseGrant creates a lease in async which expires if the server does not receive a keepAlive
 30    ///     within a given time to live period. All keys attached to the lease will be expired and
 31    ///     deleted if the lease expires. Each expired key generates a delete event in the event history.
 32    /// </summary>
 33    /// <param name="request">The request to send to the server.</param>
 34    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 35    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 36    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 37    /// <returns>The response received from the server.</returns>
 38    public async Task<LeaseGrantResponse> LeaseGrantAsync(LeaseGrantRequest request,
 39        Metadata headers = null, DateTime? deadline = null,
 1440        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 1441        .LeaseClient
 1442        .LeaseGrantAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 43
 44    /// <summary>
 45    ///     LeaseRevoke revokes a lease. All keys attached to the lease will expire and be deleted.
 46    /// </summary>
 47    /// <param name="request">The request to send to the server.</param>
 48    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 49    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 50    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 51    /// <returns>The response received from the server.</returns>
 52    public LeaseRevokeResponse LeaseRevoke(LeaseRevokeRequest request, Metadata headers = null,
 53        DateTime? deadline = null,
 2254        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.LeaseClient
 2255        .LeaseRevoke(request, headers, deadline, cancellationToken));
 56
 57    /// <summary>
 58    ///     LeaseRevoke revokes a lease in async. All keys attached to the lease will expire and be deleted.
 59    /// </summary>
 60    /// <param name="request">The request to send to the server.</param>
 61    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 62    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 63    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 64    /// <returns>The response received from the server.</returns>
 65    public async Task<LeaseRevokeResponse> LeaseRevokeAsync(LeaseRevokeRequest request,
 66        Metadata headers = null, DateTime? deadline = null,
 1267        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 1268        .LeaseClient
 1269        .LeaseRevokeAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 70
 71    /// <summary>
 72    ///     LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
 73    ///     to the server and streaming keep alive responses from the server to the client.
 74    /// </summary>
 75    /// <param name="cancellationTokenSource">
 76    ///     Cancellation token source that reflects communication status between server and
 77    ///     client.
 78    /// </param>
 79    /// <param name="leaseId">Granted lease identifier. <see cref="LeaseGrant" /> and <see cref="LeaseGrantAsync" /></pa
 80    /// <param name="keepAliveTimeout">Time to the next communication with Etcd server in milliseconds.</param>
 81    /// <param name="communicationTimeout">Time to wait response from Etcd server in milliseconds.</param>
 82    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 83    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 84    public Task LeaseKeepAlive(CancellationTokenSource cancellationTokenSource, long leaseId,
 85        int keepAliveTimeout = 1000, int? communicationTimeout = null, Metadata headers = null,
 586        DateTime? deadline = null) => CallEtcdAsync(connection =>
 587    {
 588        ArgumentNullException.ThrowIfNull(cancellationTokenSource);
 489        ArgumentOutOfRangeException.ThrowIfNegativeOrZero(keepAliveTimeout);
 390        if (communicationTimeout.HasValue)
 191        {
 192            ArgumentOutOfRangeException.ThrowIfNegativeOrZero(communicationTimeout.Value, nameof(communicationTimeout));
 093        }
 594
 295        CancellationToken cancellationToken = cancellationTokenSource.Token;
 296        int communicationTimeoutInMilliseconds = communicationTimeout ?? keepAliveTimeout / 2;
 597
 598        async ValueTask WriteAsync(AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser,
 599            LeaseKeepAliveRequest request, int timeoutInMilliseconds, CancellationToken cancellationToken)
 2100        {
 5101            // communication timeout
 2102            using CancellationTokenSource cancellationTokenSource =
 2103                CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
 2104            cancellationTokenSource.CancelAfter(timeoutInMilliseconds);
 5105
 2106            await leaser.RequestStream.WriteAsync(request, cancellationTokenSource.Token)
 2107                .ConfigureAwait(false);
 2108        }
 5109
 5110        async ValueTask<bool> MoveNextAsync(
 5111            AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser, int timeoutInMilliseconds,
 5112            CancellationToken cancellationToken)
 2113        {
 5114            // communication timeout
 2115            using CancellationTokenSource cancellationTokenSource =
 2116                CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
 2117            cancellationTokenSource.CancelAfter(timeoutInMilliseconds);
 5118
 2119            return await leaser.ResponseStream.MoveNext(cancellationTokenSource.Token)
 2120                .ConfigureAwait(false);
 2121        }
 5122
 5123        AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> LeaseKeepAlive(IConnection connection,
 5124            int timeoutInMilliseconds, CancellationToken cancellationToken)
 2125        {
 5126            // communication timeout
 2127            using CancellationTokenSource cancellationTokenSource =
 2128                CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
 2129            cancellationTokenSource.CancelAfter(timeoutInMilliseconds);
 5130
 2131            return connection.LeaseClient.LeaseKeepAlive(headers, deadline, cancellationTokenSource.Token);
 2132        }
 5133
 5134        async Task KeepAliveAsync()
 2135        {
 2136            LeaseKeepAliveRequest request = new() { ID = leaseId };
 5137
 5138            try
 2139            {
 2140                using AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser =
 2141                    LeaseKeepAlive(connection, communicationTimeoutInMilliseconds, cancellationToken);
 5142
 2143                while (!cancellationToken.IsCancellationRequested)
 2144                {
 2145                    await WriteAsync(leaser, request, communicationTimeoutInMilliseconds, cancellationToken)
 2146                        .ConfigureAwait(false);
 5147
 2148                    if (!await MoveNextAsync(leaser, communicationTimeoutInMilliseconds, cancellationToken)
 2149                            .ConfigureAwait(false))
 1150                    {
 5151                        try
 1152                        {
 1153                            if (!cancellationTokenSource.IsCancellationRequested)
 1154                            {
 5155#if NET8_0_OR_GREATER
 1156                                await cancellationTokenSource.CancelAsync()
 1157                                    .ConfigureAwait(false);
 5158#else
 5159                                    cancellationTokenSource.Cancel();
 5160#endif
 1161                            }
 1162                        }
 5163                        finally
 1164                        {
 1165                            await leaser.RequestStream.CompleteAsync()
 1166                                .ConfigureAwait(false);
 1167                        }
 5168
 1169                        break;
 5170                    }
 5171
 1172                    LeaseKeepAliveResponse update = leaser.ResponseStream.Current;
 1173                    if (update.ID != leaseId || update.TTL == 0) // expired
 1174                    {
 5175                        try
 1176                        {
 1177                            if (!cancellationTokenSource.IsCancellationRequested)
 1178                            {
 5179#if NET8_0_OR_GREATER
 1180                                await cancellationTokenSource.CancelAsync()
 1181                                    .ConfigureAwait(false);
 5182#else
 5183                                    cancellationTokenSource.Cancel();
 5184#endif
 1185                            }
 1186                        }
 5187                        finally
 1188                        {
 1189                            await leaser.RequestStream.CompleteAsync()
 1190                                .ConfigureAwait(false);
 1191                        }
 5192
 1193                        break;
 5194                    }
 5195
 0196                    await Task.Delay(keepAliveTimeout, cancellationToken)
 0197                        .ConfigureAwait(false);
 0198                }
 2199            }
 5200            finally
 2201            {
 2202                if (!cancellationTokenSource.IsCancellationRequested)
 0203                {
 5204#if NET8_0_OR_GREATER
 0205                    await cancellationTokenSource.CancelAsync()
 0206                        .ConfigureAwait(false);
 5207#else
 5208                        cancellationTokenSource.Cancel();
 5209#endif
 0210                }
 2211            }
 5212        }
 5213
 2214        return Task.Run(KeepAliveAsync, cancellationToken);
 7215    });
 216
 217    /// <summary>
 218    ///     LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
 219    ///     to the server and streaming keep alive responses from the server to the client.
 220    /// </summary>
 221    /// <param name="leaseId"></param>
 222    /// <param name="cancellationToken"></param>
 2223    public async Task LeaseKeepAlive(long leaseId, CancellationToken cancellationToken) => await CallEtcdAsync(
 2224        async connection =>
 2225        {
 2226            using (AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser =
 2227                   connection.LeaseClient.LeaseKeepAlive(cancellationToken: cancellationToken))
 2228            {
 2229                LeaseKeepAliveRequest request = new() { ID = leaseId };
 2230
 2231                while (true)
 2232                {
 2233                    cancellationToken.ThrowIfCancellationRequested();
 2234
 2235                    await leaser.RequestStream.WriteAsync(request).ConfigureAwait(false);
 2236                    if (!await leaser.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 1237                    {
 1238                        await leaser.RequestStream.CompleteAsync().ConfigureAwait(false);
 1239                        throw new EndOfStreamException();
 2240                    }
 2241
 1242                    LeaseKeepAliveResponse update = leaser.ResponseStream.Current;
 1243                    if (update.ID != leaseId || update.TTL == 0) // expired
 1244                    {
 1245                        await leaser.RequestStream.CompleteAsync().ConfigureAwait(false);
 1246                        return;
 2247                    }
 2248
 0249                    await Task.Delay(TimeSpan.FromMilliseconds(update.TTL * 1000 / 3), cancellationToken)
 0250                        .ConfigureAwait(false);
 0251                }
 2252            }
 3253        }).ConfigureAwait(false);
 254
 255    /// <summary>
 256    ///     LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
 257    ///     to the server and streaming keep alive responses from the server to the client.
 258    /// </summary>
 259    /// <param name="request">The request to send to the server.</param>
 260    /// <param name="method"></param>
 261    /// <param name="cancellationToken"></param>
 262    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 263    public async Task LeaseKeepAlive(LeaseKeepAliveRequest request, Action<LeaseKeepAliveResponse> method,
 1264        CancellationToken cancellationToken, Metadata headers = null) => await CallEtcdAsync(async connection =>
 1265    {
 1266        using (AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser =
 1267               connection.LeaseClient
 1268                   .LeaseKeepAlive(headers, cancellationToken: cancellationToken))
 1269        {
 1270            Task leaserTask = Task.Run(async () =>
 1271            {
 2272                while (await leaser.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 1273                {
 1274                    LeaseKeepAliveResponse update = leaser.ResponseStream.Current;
 1275                    method(update);
 1276                }
 2277            }, cancellationToken);
 1278
 1279            await leaser.RequestStream.WriteAsync(request).ConfigureAwait(false);
 1280            await leaser.RequestStream.CompleteAsync().ConfigureAwait(false);
 1281            await leaserTask.ConfigureAwait(false);
 1282        }
 2283    }).ConfigureAwait(false);
 284
 285    /// <summary>
 286    ///     LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
 287    ///     to the server and streaming keep alive responses from the server to the client.
 288    /// </summary>
 289    /// <param name="request">The request to send to the server.</param>
 290    /// <param name="methods"></param>
 291    /// <param name="cancellationToken"></param>
 292    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 293    public async Task LeaseKeepAlive(LeaseKeepAliveRequest request, Action<LeaseKeepAliveResponse>[] methods,
 1294        CancellationToken cancellationToken, Metadata headers = null) => await CallEtcdAsync(async connection =>
 1295    {
 1296        using (AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser =
 1297               connection.LeaseClient
 1298                   .LeaseKeepAlive(headers, cancellationToken: cancellationToken))
 1299        {
 1300            Task leaserTask = Task.Run(async () =>
 1301            {
 2302                while (await leaser.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 1303                {
 1304                    LeaseKeepAliveResponse update = leaser.ResponseStream.Current;
 7305                    foreach (Action<LeaseKeepAliveResponse> method in methods)
 2306                    {
 2307                        method(update);
 2308                    }
 1309                }
 2310            }, cancellationToken);
 1311
 1312            await leaser.RequestStream.WriteAsync(request).ConfigureAwait(false);
 1313            await leaser.RequestStream.CompleteAsync().ConfigureAwait(false);
 1314            await leaserTask.ConfigureAwait(false);
 1315        }
 2316    }).ConfigureAwait(false);
 317
 318
 319    /// <summary>
 320    ///     LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
 321    ///     to the server and streaming keep alive responses from the server to the client.
 322    /// </summary>
 323    /// <param name="requests"></param>
 324    /// <param name="method"></param>
 325    /// <param name="cancellationToken"></param>
 326    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 327    public async Task LeaseKeepAlive(LeaseKeepAliveRequest[] requests, Action<LeaseKeepAliveResponse> method,
 1328        CancellationToken cancellationToken, Metadata headers = null) => await CallEtcdAsync(async connection =>
 1329    {
 1330        using (AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser =
 1331               connection.LeaseClient
 1332                   .LeaseKeepAlive(headers, cancellationToken: cancellationToken))
 1333        {
 1334            Task leaserTask = Task.Run(async () =>
 1335            {
 2336                while (await leaser.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 1337                {
 1338                    LeaseKeepAliveResponse update = leaser.ResponseStream.Current;
 1339                    method(update);
 1340                }
 2341            }, cancellationToken);
 1342
 7343            foreach (LeaseKeepAliveRequest request in requests)
 2344            {
 2345                await leaser.RequestStream.WriteAsync(request).ConfigureAwait(false);
 2346            }
 1347
 1348            await leaser.RequestStream.CompleteAsync().ConfigureAwait(false);
 1349            await leaserTask.ConfigureAwait(false);
 1350        }
 2351    }).ConfigureAwait(false);
 352
 353    /// <summary>
 354    ///     LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
 355    ///     to the server and streaming keep alive responses from the server to the client.
 356    /// </summary>
 357    /// <param name="requests"></param>
 358    /// <param name="methods"></param>
 359    /// <param name="cancellationToken"></param>
 360    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 361    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 362    public async Task LeaseKeepAlive(LeaseKeepAliveRequest[] requests, Action<LeaseKeepAliveResponse>[] methods,
 1363        CancellationToken cancellationToken, Metadata headers = null, DateTime? deadline = null) => await CallEtcdAsync(
 1364        async connection =>
 1365        {
 1366            using (AsyncDuplexStreamingCall<LeaseKeepAliveRequest, LeaseKeepAliveResponse> leaser =
 1367                   connection.LeaseClient
 1368                       .LeaseKeepAlive(headers, deadline, cancellationToken))
 1369            {
 1370                Task leaserTask = Task.Run(async () =>
 1371                {
 2372                    while (await leaser.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 1373                    {
 1374                        LeaseKeepAliveResponse update = leaser.ResponseStream.Current;
 7375                        foreach (Action<LeaseKeepAliveResponse> method in methods)
 2376                        {
 2377                            method(update);
 2378                        }
 1379                    }
 2380                }, cancellationToken);
 1381
 7382                foreach (LeaseKeepAliveRequest request in requests)
 2383                {
 2384                    await leaser.RequestStream.WriteAsync(request).ConfigureAwait(false);
 2385                }
 1386
 1387                await leaser.RequestStream.CompleteAsync().ConfigureAwait(false);
 1388                await leaserTask.ConfigureAwait(false);
 1389            }
 2390        }).ConfigureAwait(false);
 391
 392    /// <summary>
 393    ///     LeaseTimeToLive retrieves lease information.
 394    /// </summary>
 395    /// <param name="request">The request to send to the server.</param>
 396    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 397    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 398    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 399    /// <returns>The response received from the server.</returns>
 400    public LeaseTimeToLiveResponse LeaseTimeToLive(LeaseTimeToLiveRequest request,
 401        Metadata headers = null, DateTime? deadline = null,
 6402        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.LeaseClient
 6403        .LeaseTimeToLive(request, headers, deadline, cancellationToken));
 404
 405    /// <summary>
 406    ///     LeaseTimeToLive retrieves lease information.
 407    /// </summary>
 408    /// <param name="request">The request to send to the server.</param>
 409    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 410    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 411    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 412    /// <returns>The call object.</returns>
 413    public async Task<LeaseTimeToLiveResponse> LeaseTimeToLiveAsync(LeaseTimeToLiveRequest request,
 414        Metadata headers = null, DateTime? deadline = null,
 6415        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6416        .LeaseClient
 6417        .LeaseTimeToLiveAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 418}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/lockClient.cs

#LineLine coverage
 1using System;
 2using System.Threading;
 3using System.Threading.Tasks;
 4using Google.Protobuf;
 5using Grpc.Core;
 6using V3Lockpb;
 7
 8namespace dotnet_etcd;
 9
 10public partial class EtcdClient
 11{
 12    /// <summary>
 13    ///     Lock acquires a distributed shared lock on a given named lock.
 14    ///     On success, it will return a unique key that exists so long as the
 15    ///     lock is held by the caller. This key can be used in conjunction with
 16    ///     transactions to safely ensure updates to etcd only occur while holding
 17    ///     lock ownership. The lock is held until Unlock is called on the key or the
 18    ///     lease associate with the owner expires.
 19    /// </summary>
 20    /// <param name="name">is the identifier for the distributed shared lock to be acquired.</param>
 21    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 22    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 23    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 24    /// <returns>The response received from the server.</returns>
 25    public LockResponse Lock(string name, Metadata headers = null, DateTime? deadline = null,
 226        CancellationToken cancellationToken = default) => Lock(new LockRequest { Name = ByteString.CopyFromUtf8(name) },
 227        headers, deadline, cancellationToken);
 28
 29    /// <summary>
 30    ///     Lock acquires a distributed shared lock on a given named lock.
 31    ///     On success, it will return a unique key that exists so long as the
 32    ///     lock is held by the caller. This key can be used in conjunction with
 33    ///     transactions to safely ensure updates to etcd only occur while holding
 34    ///     lock ownership. The lock is held until Unlock is called on the key or the
 35    ///     lease associate with the owner expires.
 36    /// </summary>
 37    /// <param name="request">The request to send to the server</param>
 38    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 39    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 40    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 41    /// <returns>The response received from the server.</returns>
 42    public LockResponse Lock(LockRequest request, Metadata headers = null, DateTime? deadline = null,
 543        CancellationToken cancellationToken = default) => CallEtcd(connection =>
 1044        connection.LockClient.Lock(request, headers, deadline, cancellationToken));
 45
 46    /// <summary>
 47    ///     LockAsync acquires a distributed shared lock on a given named lock.
 48    ///     On success, it will return a unique key that exists so long as the
 49    ///     lock is held by the caller. This key can be used in conjunction with
 50    ///     transactions to safely ensure updates to etcd only occur while holding
 51    ///     lock ownership. The lock is held until Unlock is called on the key or the
 52    ///     lease associate with the owner expires.
 53    /// </summary>
 54    /// <param name="name">is the identifier for the distributed shared lock to be acquired.</param>
 55    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 56    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 57    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 58    /// <returns>The response received from the server.</returns>
 59    public async Task<LockResponse> LockAsync(string name, Metadata headers = null,
 60        DateTime? deadline = null, CancellationToken cancellationToken = default) =>
 261        await LockAsync(new LockRequest { Name = ByteString.CopyFromUtf8(name) }, headers, deadline, cancellationToken)
 262            .ConfigureAwait(false);
 63
 64    /// <summary>
 65    ///     LockAsync acquires a distributed shared lock on a given named lock.
 66    ///     On success, it will return a unique key that exists so long as the
 67    ///     lock is held by the caller. This key can be used in conjunction with
 68    ///     transactions to safely ensure updates to etcd only occur while holding
 69    ///     lock ownership. The lock is held until Unlock is called on the key or the
 70    ///     lease associate with the owner expires.
 71    /// </summary>
 72    /// <param name="request">The request to send to the server</param>
 73    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 74    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 75    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 76    /// <returns>The response received from the server.</returns>
 77    public async Task<LockResponse> LockAsync(LockRequest request, Metadata headers = null,
 978        DateTime? deadline = null, CancellationToken cancellationToken = default) => await CallEtcdAsync(
 1879        async connection => await connection.LockClient
 1880            .LockAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 81
 82    /// <summary>
 83    ///     Unlock takes a key returned by Lock and releases the hold on lock. The
 84    ///     next Lock caller waiting for the lock will then be woken up and given
 85    ///     ownership of the lock.
 86    /// </summary>
 87    /// <param name="key">the lock ownership key granted by Lock.</param>
 88    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 89    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 90    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 91    /// <returns>The response received from the server.</returns>
 92    public UnlockResponse Unlock(string key, Metadata headers = null, DateTime? deadline = null,
 93        CancellationToken cancellationToken = default) =>
 294        Unlock(new UnlockRequest { Key = ByteString.CopyFromUtf8(key) }, headers, deadline, cancellationToken);
 95
 96    /// <summary>
 97    ///     Unlock takes a key returned by Lock and releases the hold on lock. The
 98    ///     next Lock caller waiting for the lock will then be woken up and given
 99    ///     ownership of the lock.
 100    /// </summary>
 101    /// <param name="request">The request to send to the server</param>
 102    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 103    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 104    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 105    /// <returns>The response received from the server.</returns>
 106    public UnlockResponse Unlock(UnlockRequest request, Metadata headers = null,
 10107        DateTime? deadline = null, CancellationToken cancellationToken = default) => CallEtcd(connection => connection
 10108        .LockClient
 10109        .Unlock(request, headers, deadline, cancellationToken));
 110
 111    /// <summary>
 112    ///     UnlockAsync takes a key returned by Lock and releases the hold on lock. The
 113    ///     next Lock caller waiting for the lock will then be woken up and given
 114    ///     ownership of the lock.
 115    /// </summary>
 116    /// <param name="key">the lock ownership key granted by Lock.</param>
 117    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 118    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 119    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 120    /// <returns>The response received from the server.</returns>
 121    public async Task<UnlockResponse> UnlockAsync(string key, Metadata headers = null,
 122        DateTime? deadline = null, CancellationToken cancellationToken = default) =>
 2123        await UnlockAsync(new UnlockRequest { Key = ByteString.CopyFromUtf8(key) }, headers, deadline,
 2124            cancellationToken).ConfigureAwait(false);
 125
 126    /// <summary>
 127    ///     UnlockAsync takes a key returned by Lock and releases the hold on lock. The
 128    ///     next Lock caller waiting for the lock will then be woken up and given
 129    ///     ownership of the lock.
 130    /// </summary>
 131    /// <param name="request">The request to send to the server</param>
 132    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 133    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 134    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 135    /// <returns>The response received from the server.</returns>
 136    public async Task<UnlockResponse> UnlockAsync(UnlockRequest request, Metadata headers = null,
 8137        DateTime? deadline = null, CancellationToken cancellationToken = default) => await CallEtcdAsync(
 16138        async connection => await connection.LockClient
 16139            .UnlockAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 140}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/maintenanceClient.cs

#LineLine coverage
 1using System;
 2using System.Threading;
 3using System.Threading.Tasks;
 4using Etcdserverpb;
 5using Grpc.Core;
 6
 7namespace dotnet_etcd;
 8
 9public partial class EtcdClient
 10{
 11    /// <summary>
 12    ///     Alarm activates, deactivates, and queries alarms regarding cluster health
 13    /// </summary>
 14    /// <param name="request">Alarm request</param>
 15    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 16    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 17    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 18    /// <returns>Alarm Response</returns>
 19    public AlarmResponse Alarm(AlarmRequest request, Metadata headers = null, DateTime? deadline = null,
 620        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.MaintenanceClient
 621        .Alarm(request, headers, deadline, cancellationToken));
 22
 23    /// <summary>
 24    ///     Alarm activates, deactivates, and queries alarms regarding cluster health in async
 25    /// </summary>
 26    /// <param name="request">Alarm request</param>
 27    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 28    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 29    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 30    /// <returns>Alarm Response</returns>
 31    public async Task<AlarmResponse> AlarmAsync(AlarmRequest request, Metadata headers = null,
 32        DateTime? deadline = null,
 633        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 634        .MaintenanceClient
 635        .AlarmAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 36
 37    /// <summary>
 38    ///     Status gets the status of the member.
 39    /// </summary>
 40    /// <param name="request">Status Request</param>
 41    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 42    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 43    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 44    /// <returns>Status response</returns>
 45    public StatusResponse Status(StatusRequest request, Metadata headers = null,
 46        DateTime? deadline = null,
 1247        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.MaintenanceClient
 1248        .Status(request, headers, deadline, cancellationToken));
 49
 50    /// <summary>
 51    ///     Status gets the status of the member in async.
 52    /// </summary>
 53    /// <param name="request">Status Request</param>
 54    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 55    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 56    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 57    /// <returns>Status response</returns>
 58    public async Task<StatusResponse> StatusAsync(StatusRequest request, Metadata headers = null,
 59        DateTime? deadline = null,
 1660        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 1661        .MaintenanceClient
 1662        .StatusAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 63
 64    /// <summary>
 65    ///     Defragment defragments a member's backend database to recover storage space.
 66    /// </summary>
 67    /// <param name="request">Defragment Request</param>
 68    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 69    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 70    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 71    /// <returns>Defragment Response</returns>
 72    public DefragmentResponse Defragment(DefragmentRequest request, Metadata headers = null,
 73        DateTime? deadline = null,
 674        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.MaintenanceClient
 675        .Defragment(request, headers, deadline, cancellationToken));
 76
 77    /// <summary>
 78    ///     Defragment defragments a member's backend database to recover storage space in async.
 79    /// </summary>
 80    /// <param name="request">Defragment Request</param>
 81    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 82    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 83    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 84    /// <returns>Defragment Response</returns>
 85    public async Task<DefragmentResponse> DefragmentAsync(DefragmentRequest request,
 86        Metadata headers = null, DateTime? deadline = null,
 687        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 688        .MaintenanceClient
 689        .DefragmentAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 90
 91    /// <summary>
 92    ///     Hash computes the hash of whole backend keyspace,
 93    ///     including key, lease, and other buckets in storage.
 94    ///     This is designed for testing ONLY!
 95    ///     Do not rely on this in production with ongoing transactions,
 96    ///     since Hash operation does not hold MVCC locks.
 97    ///     Use "HashKV" API instead for "key" bucket consistency checks.
 98    /// </summary>
 99    /// <param name="request">Hash Request</param>
 100    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 101    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 102    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 103    /// <returns>Hash Response</returns>
 104    public HashResponse Hash(HashRequest request, Metadata headers = null, DateTime? deadline = null,
 6105        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.MaintenanceClient
 6106        .Hash(request, headers, deadline, cancellationToken));
 107
 108    /// <summary>
 109    ///     Hash computes the hash of whole backend keyspace,
 110    ///     including key, lease, and other buckets in storage in async.
 111    ///     This is designed for testing ONLY!
 112    ///     Do not rely on this in production with ongoing transactions,
 113    ///     since Hash operation does not hold MVCC locks.
 114    ///     Use "HashKV" API instead for "key" bucket consistency checks.
 115    /// </summary>
 116    /// <param name="request">Hash Request</param>
 117    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 118    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 119    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 120    /// <returns>Hash Response</returns>
 121    public async Task<HashResponse> HashAsync(HashRequest request, Metadata headers = null,
 122        DateTime? deadline = null,
 6123        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 6124        .MaintenanceClient
 6125        .HashAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 126
 127    /// <summary>
 128    ///     HashKV computes the hash of all MVCC keys up to a given revision.
 129    ///     It only iterates "key" bucket in backend storage.
 130    /// </summary>
 131    /// <param name="request">HashKV Request</param>
 132    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 133    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 134    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 135    /// <returns>HashKV Response</returns>
 136    public HashKVResponse HashKV(HashKVRequest request, Metadata headers = null,
 137        DateTime? deadline = null,
 8138        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.MaintenanceClient
 8139        .HashKV(request, headers, deadline, cancellationToken));
 140
 141    /// <summary>
 142    ///     HashKV computes the hash of all MVCC keys up to a given revision in async.
 143    ///     It only iterates "key" bucket in backend storage.
 144    /// </summary>
 145    /// <param name="request">HashKV Request</param>
 146    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 147    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 148    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 149    /// <returns>HashKV Response</returns>
 150    public async Task<HashKVResponse> HashKVAsync(HashKVRequest request, Metadata headers = null,
 151        DateTime? deadline = null,
 8152        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 8153        .MaintenanceClient
 8154        .HashKVAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 155
 156    /// <summary>
 157    ///     Snapshot sends a snapshot of the entire backend from a member over a stream to a client.
 158    /// </summary>
 159    /// <param name="request">The request to send to the server.</param>
 160    /// <param name="method"></param>
 161    /// <param name="cancellationToken"></param>
 162    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 163    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 164    public async Task Snapshot(SnapshotRequest request, Action<SnapshotResponse> method,
 1165        CancellationToken cancellationToken, Metadata headers = null, DateTime? deadline = null) => await CallEtcdAsync(
 1166        async connection =>
 1167        {
 1168            using (AsyncServerStreamingCall<SnapshotResponse> snapshotter = connection
 1169                       .MaintenanceClient.Snapshot(request, headers, deadline, cancellationToken))
 1170            {
 3171                while (await snapshotter.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 2172                {
 2173                    SnapshotResponse update = snapshotter.ResponseStream.Current;
 2174                    method(update);
 2175                }
 1176            }
 2177        }).ConfigureAwait(false);
 178
 179    /// <summary>
 180    ///     Snapshot sends a snapshot of the entire backend from a member over a stream to a client.
 181    /// </summary>
 182    /// <param name="request">The request to send to the server.</param>
 183    /// <param name="methods"></param>
 184    /// <param name="cancellationToken"></param>
 185    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 186    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 187    public async Task Snapshot(SnapshotRequest request, Action<SnapshotResponse>[] methods,
 1188        CancellationToken cancellationToken, Metadata headers = null, DateTime? deadline = null) => await CallEtcdAsync(
 1189        async connection =>
 1190        {
 1191            using (AsyncServerStreamingCall<SnapshotResponse> snapshotter = connection
 1192                       .MaintenanceClient.Snapshot(request, headers, deadline, cancellationToken))
 1193            {
 2194                while (await snapshotter.ResponseStream.MoveNext(cancellationToken).ConfigureAwait(false))
 1195                {
 1196                    SnapshotResponse update = snapshotter.ResponseStream.Current;
 7197                    foreach (Action<SnapshotResponse> method in methods)
 2198                    {
 2199                        method(update);
 2200                    }
 1201                }
 1202            }
 2203        }).ConfigureAwait(false);
 204
 205    /// <summary>
 206    ///     MoveLeader requests current leader node to transfer its leadership to transferee.
 207    /// </summary>
 208    /// <param name="request">MoveLeader Request</param>
 209    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 210    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 211    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 212    /// <returns>MoveLeader Response</returns>
 213    public MoveLeaderResponse MoveLeader(MoveLeaderRequest request, Metadata headers = null,
 214        DateTime? deadline = null,
 2215        CancellationToken cancellationToken = default) => CallEtcd(connection => connection.MaintenanceClient
 2216        .MoveLeader(request, headers, deadline, cancellationToken));
 217
 218    /// <summary>
 219    ///     MoveLeader requests current leader node to transfer its leadership to transferee in async.
 220    /// </summary>
 221    /// <param name="request">MoveLeader Request</param>
 222    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 223    /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
 224    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 225    /// <returns>MoveLeader Response</returns>
 226    public async Task<MoveLeaderResponse> MoveLeaderAsync(MoveLeaderRequest request,
 227        Metadata headers = null, DateTime? deadline = null,
 2228        CancellationToken cancellationToken = default) => await CallEtcdAsync(async connection => await connection
 2229        .MaintenanceClient
 2230        .MoveLeaderAsync(request, headers, deadline, cancellationToken)).ConfigureAwait(false);
 231}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/Util.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Threading.Tasks;
 5using dotnet_etcd.interfaces;
 6using dotnet_etcd.multiplexer;
 7using Etcdserverpb;
 8using Google.Protobuf;
 9using Grpc.Core;
 10using Mvccpb;
 11
 12namespace dotnet_etcd;
 13
 14public partial class EtcdClient
 15{
 16    private const string rangeEndString = "\x00";
 17
 18    /// <summary>
 19    ///     Converts RangeResponse to Dictionary
 20    /// </summary>
 21    /// <returns>IDictionary corresponding the RangeResponse</returns>
 22    /// <param name="resp">RangeResponse received from etcd server</param>
 23    private static Dictionary<string, string> RangeRespondToDictionary(RangeResponse resp)
 324    {
 325        Dictionary<string, string> resDictionary = new();
 2126        foreach (KeyValue kv in resp.Kvs)
 627        {
 628            resDictionary.Add(kv.Key.ToStringUtf8(), kv.Value.ToStringUtf8());
 629        }
 30
 331        return resDictionary;
 332    }
 33
 34    /// <summary>
 35    ///     Gets the range end for prefix
 36    /// </summary>
 37    /// <returns>The range end for prefix</returns>
 38    /// <param name="prefixKey">Prefix key</param>
 39    public static string GetRangeEnd(string prefixKey)
 5940    {
 5941        if (prefixKey.Length == 0)
 042        {
 043            return rangeEndString;
 44        }
 45
 5946        StringBuilder rangeEnd = new(prefixKey);
 5947        rangeEnd[rangeEnd.Length - 1] = ++rangeEnd[rangeEnd.Length - 1];
 5948        return rangeEnd.ToString();
 5949    }
 50
 51    /// <summary>
 52    ///     Gets the byte string for range requests
 53    /// </summary>
 54    /// <param name="key"></param>
 55    /// <returns></returns>
 56    public static ByteString GetStringByteForRangeRequests(string key) =>
 2257        key.Length == 0 ? ByteString.CopyFrom(0) : ByteString.CopyFromUtf8(key);
 58
 59    /// <summary>
 60    ///     Generic helper for performing actions an a connection.
 61    ///     Gets the connection from the <seealso cref="Balancer" />
 62    ///     Also implements a retry mechanism if the calling methods returns an <seealso cref="RpcException" /> with the
 63    ///     <seealso cref="StatusCode" /> <seealso cref="StatusCode.Unavailable" />
 64    /// </summary>
 65    /// <typeparam name="TResponse">The type of the response that is returned from the call to etcd</typeparam>
 66    /// <param name="etcdCallFunc">The function to perform actions with the <seealso cref="Connection" /> object</param>
 67    /// <returns>The response from the the <paramref name="etcdCallFunc" /></returns>
 16968    private TResponse CallEtcd<TResponse>(Func<IConnection, TResponse> etcdCallFunc) => etcdCallFunc(_connection);
 69
 70    /// <summary>
 71    ///     Generic helper for performing actions an a connection.
 72    ///     Gets the connection from the <seealso cref="Balancer" />
 73    ///     Also implements a retry mechanism if the calling methods returns an <seealso cref="RpcException" /> with the
 74    ///     <seealso cref="StatusCode" /> <seealso cref="StatusCode.Unavailable" />
 75    /// </summary>
 76    /// <typeparam name="TResponse">The type of the response that is returned from the call to etcd</typeparam>
 77    /// <param name="etcdCallFunc">The function to perform actions with the <seealso cref="Connection" /> object</param>
 78    /// <returns>The response from the the <paramref name="etcdCallFunc" /></returns>
 79    private Task<TResponse> CallEtcdAsync<TResponse>(Func<IConnection, Task<TResponse>> etcdCallFunc) =>
 51480        etcdCallFunc(_connection);
 81
 82    /// <summary>
 83    ///     Generic helper for performing actions an a connection.
 84    ///     Gets the connection from the <seealso cref="Balancer" />
 85    ///     Also implements a retry mechanism if the calling methods returns an <seealso cref="RpcException" /> with the
 86    ///     <seealso cref="StatusCode" /> <seealso cref="StatusCode.Unavailable" />
 87    /// </summary>
 88    /// <param name="etcdCallFunc">The function to perform actions with the <seealso cref="Connection" /> object</param>
 89    /// <returns>The response from the the <paramref name="etcdCallFunc" /></returns>
 1390    private Task CallEtcdAsync(Func<IConnection, Task> etcdCallFunc) => etcdCallFunc(_connection);
 91}

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/watchclient/watchClient.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading;
 5using System.Threading.Tasks;
 6using Etcdserverpb;
 7using Google.Protobuf;
 8using Grpc.Core;
 9
 10namespace dotnet_etcd;
 11
 12public partial class EtcdClient
 13{
 14    /// <summary>
 15    ///     Watches the specified requests and passes the watch events to the methods provided asynchronously.
 16    /// </summary>
 17    /// <param name="requests">Watch Requests containing keys to be watched</param>
 18    /// <param name="methods">Methods to which watch events should be passed on</param>
 19    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 20    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 21    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 22    /// <returns>A task that completes with an array of watch IDs</returns>
 23    public async Task<long[]> WatchAsync(WatchRequest[] requests, Action<WatchEvent[]>[] methods,
 24        Metadata headers = null,
 25        DateTime? deadline = null,
 26        CancellationToken cancellationToken = default)
 427    {
 428        if (requests.Length != methods.Length)
 129        {
 130            throw new ArgumentException("The number of requests must match the number of methods");
 31        }
 32
 333        long[] watchIds = new long[requests.Length];
 34
 1635        for (int i = 0; i < requests.Length; i++)
 536        {
 37            // Capture the loop index per iteration; otherwise the closure below would read the
 38            // shared loop variable (== requests.Length when an event later arrives) and throw
 39            // IndexOutOfRangeException, silently dropping every event.
 540            int index = i;
 41
 42            // Create a wrapper that converts WatchResponse to WatchEvent[]
 543            Action<WatchResponse> wrapper = response =>
 244            {
 445                WatchEvent[] events = response.Events.Select(e => new WatchEvent
 446                {
 447                    Key = e.Kv.Key.ToStringUtf8(), Value = e.Kv.Value.ToStringUtf8(), Type = e.Type
 448                }).ToArray();
 549
 250                methods[index](events);
 751            };
 52
 553            watchIds[i] = await _watchManager.WatchAsync(requests[i], wrapper, headers, deadline, cancellationToken)
 554                .ConfigureAwait(false);
 555        }
 56
 357        return watchIds;
 358    }
 59
 60    public Task<long[]> WatchAsync(WatchRequest[] requests, Action<WatchEvent[]> method, Metadata headers = null,
 61        DateTime? deadline = null, CancellationToken cancellationToken = default)
 162    {
 163        List<Task<long>> tasks = [];
 64
 765        foreach (WatchRequest request in requests)
 266        {
 67            // Create a wrapper that converts WatchResponse to WatchEvent[]
 268            Action<WatchResponse> wrapper = response =>
 269            {
 470                WatchEvent[] events = response.Events.Select(e => new WatchEvent
 471                {
 472                    Key = e.Kv.Key.ToStringUtf8(), Value = e.Kv.Value.ToStringUtf8(), Type = e.Type
 473                }).ToArray();
 274
 275                method(events);
 476            };
 77
 278            tasks.Add(_watchManager.WatchAsync(request, wrapper, headers, deadline, cancellationToken));
 279        }
 80
 181        return Task.WhenAll(tasks);
 182    }
 83    // CancelWatch methods are already defined in EtcdClient.cs
 84
 85    /// <summary>
 86    ///     Watches the specified requests and passes the watch response to the methods provided.
 87    /// </summary>
 88    /// <param name="requests">Watch Requests containing keys to be watched</param>
 89    /// <param name="methods">Methods to which a watch response should be passed on</param>
 90    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 91    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 92    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 93    public void Watch(WatchRequest[] requests, Action<WatchResponse>[] methods, Metadata headers = null,
 94        DateTime? deadline = null,
 95        CancellationToken cancellationToken = default)
 1296    {
 1297        if (requests.Length != methods.Length)
 198        {
 199            throw new ArgumentException("The number of requests must match the number of methods");
 100        }
 101
 46102        for (int i = 0; i < requests.Length; i++)
 12103        {
 12104            _watchManager.Watch(requests[i], methods[i], headers, deadline, cancellationToken);
 12105        }
 11106    }
 107
 108    /// <summary>
 109    ///     Watches the specified requests and passes the watch events to the methods provided.
 110    /// </summary>
 111    /// <param name="requests">Watch Requests containing keys to be watched</param>
 112    /// <param name="methods">Methods to which watch events should be passed on</param>
 113    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 114    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 115    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 116    public void Watch(WatchRequest[] requests, Action<WatchEvent[]>[] methods, Metadata headers = null,
 117        DateTime? deadline = null,
 118        CancellationToken cancellationToken = default)
 3119    {
 3120        if (requests.Length != methods.Length)
 0121        {
 0122            throw new ArgumentException("The number of requests must match the number of methods");
 123        }
 124
 16125        for (int i = 0; i < requests.Length; i++)
 5126        {
 127            // Capture the loop index per iteration; otherwise the closure below would read the
 128            // shared loop variable (== requests.Length when an event later arrives) and throw
 129            // IndexOutOfRangeException, silently dropping every event.
 5130            int index = i;
 131
 132            // Create a wrapper that converts WatchResponse to WatchEvent[]
 5133            Action<WatchResponse> wrapper = response =>
 2134            {
 4135                WatchEvent[] events = [.. response.Events.Select(e => new WatchEvent
 4136                {
 4137                    Key = e.Kv.Key.ToStringUtf8(), Value = e.Kv.Value.ToStringUtf8(), Type = e.Type
 4138                })];
 5139
 2140                methods[index](events);
 7141            };
 142
 5143            _watchManager.Watch(requests[i], wrapper, headers, deadline, cancellationToken);
 5144        }
 3145    }
 146
 147    #region Watch Key
 148
 149    /// <summary>
 150    ///     Watches a key according to the specified watch request and
 151    ///     passes the watch response to the method provided.
 152    /// </summary>
 153    /// <param name="request">Watch Request containing a key to be watched</param>
 154    /// <param name="method">Method to which a watch response should be passed on</param>
 155    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 156    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 157    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 158    /// <returns>A task that completes with the watch ID</returns>
 159    public Task<long> WatchAsync(WatchRequest request, Action<WatchResponse> method, Metadata headers = null,
 160        DateTime? deadline = null,
 161        CancellationToken cancellationToken = default) =>
 1162        _watchManager.WatchAsync(request, method, headers, deadline, cancellationToken);
 163
 164    /// <summary>
 165    ///     Watches a key according to the specified watch request and
 166    ///     passes the watch response to the methods provided.
 167    /// </summary>
 168    /// <param name="request">Watch Request containing a key to be watched</param>
 169    /// <param name="methods">Methods to which a watch response should be passed on</param>
 170    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 171    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 172    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 173    /// <returns>A task that completes with the watch ID</returns>
 174    public Task<long> WatchAsync(WatchRequest request, Action<WatchResponse>[] methods, Metadata headers = null,
 175        DateTime? deadline = null,
 176        CancellationToken cancellationToken = default)
 1177    {
 178        // Create a wrapper method that calls all the methods
 1179        Action<WatchResponse> wrapper = response =>
 1180        {
 7181            foreach (Action<WatchResponse> method in methods)
 2182            {
 2183                method(response);
 2184            }
 2185        };
 186
 1187        return _watchManager.WatchAsync(request, wrapper, headers, deadline, cancellationToken);
 1188    }
 189
 190    /// <summary>
 191    ///     Watches a key according to the specified watch requests and
 192    ///     passes the watch response to the method provided.
 193    /// </summary>
 194    /// <param name="requests">Watch Requests containing keys to be watched</param>
 195    /// <param name="method">Method to which a watch response should be passed on</param>
 196    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 197    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 198    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 199    /// <returns>A task that completes with an array of watch IDs</returns>
 200    public async Task<long[]> WatchAsync(WatchRequest[] requests, Action<WatchResponse> method, Metadata headers = null,
 201        DateTime? deadline = null,
 202        CancellationToken cancellationToken = default)
 1203    {
 1204        long[] watchIds = new long[requests.Length];
 205
 6206        for (int i = 0; i < requests.Length; i++)
 2207        {
 2208            watchIds[i] = await _watchManager.WatchAsync(requests[i], method, headers, deadline, cancellationToken)
 2209                .ConfigureAwait(false);
 2210        }
 211
 1212        return watchIds;
 1213    }
 214
 215    /// <summary>
 216    ///     Watches a key according to the specified watch requests and
 217    ///     passes the watch response to the methods provided.
 218    /// </summary>
 219    /// <param name="requests">Watch Requests containing keys to be watched</param>
 220    /// <param name="methods">Methods to which a watch response should be passed on</param>
 221    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 222    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 223    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 224    /// <returns>A task that completes with an array of watch IDs</returns>
 225    public async Task<long[]> WatchAsync(WatchRequest[] requests, Action<WatchResponse>[] methods,
 226        Metadata headers = null,
 227        DateTime? deadline = null,
 228        CancellationToken cancellationToken = default)
 2229    {
 2230        if (requests.Length != methods.Length)
 0231        {
 0232            throw new ArgumentException("The number of requests must match the number of methods");
 233        }
 234
 2235        long[] watchIds = new long[requests.Length];
 236
 10237        for (int i = 0; i < requests.Length; i++)
 3238        {
 3239            watchIds[i] = await _watchManager.WatchAsync(requests[i], methods[i], headers, deadline, cancellationToken)
 3240                .ConfigureAwait(false);
 3241        }
 242
 2243        return watchIds;
 2244    }
 245
 246    /// <summary>
 247    ///     Watches a key according to the specified watch request and
 248    ///     passes the minimal watch event data to the method provided.
 249    /// </summary>
 250    /// <param name="request">Watch Request containing a key to be watched</param>
 251    /// <param name="method">Method to which minimal watch events data should be passed on</param>
 252    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 253    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 254    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 255    public Task WatchAsync(WatchRequest request, Action<WatchEvent[]> method, Metadata headers = null,
 256        DateTime? deadline = null,
 257        CancellationToken cancellationToken = default)
 1258    {
 259        // Create a wrapper that converts WatchResponse to WatchEvent[]
 1260        Action<WatchResponse> wrapper = response =>
 1261        {
 1262            WatchEvent[] events = response.Events.Select(i =>
 1263            {
 1264                return new WatchEvent
 1265                {
 1266                    Key = i.Kv.Key.ToStringUtf8(), Value = i.Kv.Value.ToStringUtf8(), Type = i.Type
 1267                };
 2268            }).ToArray();
 1269
 1270            method(events);
 2271        };
 272
 1273        return _watchManager.WatchAsync(request, wrapper, headers, deadline, cancellationToken);
 1274    }
 275
 276    /// <summary>
 277    ///     Watches a key according to the specified watch request and
 278    ///     passes the minimal watch event data to the methods provided.
 279    /// </summary>
 280    /// <param name="request">Watch Request containing a key to be watched</param>
 281    /// <param name="methods">Methods to which minimal watch events data should be passed on</param>
 282    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 283    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 284    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 285    public Task WatchAsync(WatchRequest request, Action<WatchEvent[]>[] methods, Metadata headers = null,
 286        DateTime? deadline = null,
 287        CancellationToken cancellationToken = default)
 1288    {
 289        // Create a wrapper that converts WatchResponse to WatchEvent[] and calls all methods
 1290        Action<WatchResponse> wrapper = response =>
 1291        {
 1292            WatchEvent[] events = response.Events.Select(i =>
 1293            {
 1294                return new WatchEvent
 1295                {
 1296                    Key = i.Kv.Key.ToStringUtf8(), Value = i.Kv.Value.ToStringUtf8(), Type = i.Type
 1297                };
 2298            }).ToArray();
 1299
 7300            foreach (Action<WatchEvent[]> method in methods)
 2301            {
 2302                method(events);
 2303            }
 2304        };
 305
 1306        return _watchManager.WatchAsync(request, wrapper, headers, deadline, cancellationToken);
 1307    }
 308
 309    /// <summary>
 310    ///     Watches the specified key and passes the watch response to the method provided.
 311    /// </summary>
 312    /// <param name="request">Watch Request</param>
 313    /// <param name="method">Method to which a watch response should be passed on</param>
 314    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 315    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 316    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 317    public void Watch(WatchRequest request, Action<WatchResponse> method, Metadata headers = null,
 318        DateTime? deadline = null,
 319        CancellationToken cancellationToken = default) =>
 1320        _watchManager.Watch(request, method, headers, deadline, cancellationToken);
 321
 322    /// <summary>
 323    ///     Watches a key according to the specified watch request and
 324    ///     passes the watch response to the methods provided.
 325    /// </summary>
 326    /// <param name="request">Watch Request containing a key to be watched</param>
 327    /// <param name="methods">Methods to which a watch response should be passed on</param>
 328    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 329    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 330    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 331    public void Watch(WatchRequest request, Action<WatchResponse>[] methods,
 332        Metadata headers = null, DateTime? deadline = null,
 1333        CancellationToken cancellationToken = default) => Watch([request], methods, headers,
 1334        deadline, cancellationToken);
 335
 336
 337    /// <summary>
 338    ///     Watches the specified keys and passes the watch response to the method provided.
 339    /// </summary>
 340    /// <param name="key">Key to watch</param>
 341    /// <param name="method">Method to which a watch response should be passed on</param>
 342    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 343    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 344    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 345    public void Watch(string key, Action<WatchResponse> method, Metadata headers = null,
 346        DateTime? deadline = null,
 9347        CancellationToken cancellationToken = default) => Watch([key],
 9348        [method], headers, deadline, cancellationToken);
 349
 350    /// <summary>
 351    ///     Watches the specified key and passes the watch response to the methods provided.
 352    /// </summary>
 353    /// <param name="key">Key to be watched</param>
 354    /// <param name="methods">Methods to which a watch response should be passed on</param>
 355    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 356    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 357    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 358    public void Watch(string key, Action<WatchResponse>[] methods, Metadata headers = null,
 359        DateTime? deadline = null,
 360        CancellationToken cancellationToken = default) =>
 0361        Watch([key], methods, headers, deadline, cancellationToken);
 362
 363
 364    /// <summary>
 365    ///     Watches the specified keys and passes the watch response to the method provided.
 366    /// </summary>
 367    /// <param name="keys">Keys to be watched</param>
 368    /// <param name="method">Method to which a watch response should be passed on</param>
 369    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 370    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 371    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 372    public void Watch(string[] keys, Action<WatchResponse> method, Metadata headers = null,
 373        DateTime? deadline = null,
 0374        CancellationToken cancellationToken = default) => Watch(keys, [method], headers,
 0375        deadline, cancellationToken);
 376
 377    /// <summary>
 378    ///     Watches the specified keys and passes the watch response to the method provided.
 379    /// </summary>
 380    /// <param name="keys">Keys to be watched</param>
 381    /// <param name="methods">Methods to which a watch response should be passed on</param>
 382    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 383    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 384    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 385    public void Watch(string[] keys, Action<WatchResponse>[] methods, Metadata headers = null,
 386        DateTime? deadline = null,
 387        CancellationToken cancellationToken = default)
 9388    {
 9389        List<WatchRequest> requests = [];
 390
 45391        foreach (string key in keys)
 9392        {
 9393            WatchRequest request = new()
 9394            {
 9395                CreateRequest = new WatchCreateRequest
 9396                {
 9397                    Key = ByteString.CopyFromUtf8(key), ProgressNotify = true, PrevKv = true
 9398                }
 9399            };
 9400            requests.Add(request);
 9401        }
 402
 9403        Watch(requests.ToArray(), methods, headers, deadline, cancellationToken);
 9404    }
 405
 406
 407    /// <summary>
 408    ///     Watches the specified key and passes the minimal watch events data to the method provided.
 409    /// </summary>
 410    /// <param name="key">Key to be watched</param>
 411    /// <param name="method">Method to which minimal watch events data should be passed on</param>
 412    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 413    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 414    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 415    public void Watch(string key, Action<WatchEvent[]> method, Metadata headers = null,
 416        DateTime? deadline = null,
 1417        CancellationToken cancellationToken = default) => Watch([key],
 1418        [method], headers, deadline, cancellationToken);
 419
 420    /// <summary>
 421    ///     Watches the specified key and passes the minimal watch events data to the methods provided.
 422    /// </summary>
 423    /// <param name="key">Key to be watched</param>
 424    /// <param name="methods">Methods to which minimal watch events data should be passed on</param>
 425    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 426    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 427    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 428    public void Watch(string key, Action<WatchEvent[]>[] methods, Metadata headers = null,
 429        DateTime? deadline = null,
 430        CancellationToken cancellationToken = default) =>
 0431        Watch([key], methods, headers, deadline, cancellationToken);
 432
 433    /// <summary>
 434    ///     Watches the specified keys and passes the minimal watch events data to the method provided.
 435    /// </summary>
 436    /// <param name="keys">Keys to be watched</param>
 437    /// <param name="method">Method to which minimal watch events data should be passed on</param>
 438    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 439    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 440    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 441    public void Watch(string[] keys, Action<WatchEvent[]> method, Metadata headers = null,
 442        DateTime? deadline = null,
 0443        CancellationToken cancellationToken = default) => Watch(keys, [method], headers,
 0444        deadline, cancellationToken);
 445
 446    /// <summary>
 447    ///     Watches the specified keys and passes the minimal watch events data to the method provided.
 448    /// </summary>
 449    /// <param name="keys">Keys to be watched</param>
 450    /// <param name="methods">Methods to which minimal watch events data should be passed on</param>
 451    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 452    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 453    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 454    public void Watch(string[] keys, Action<WatchEvent[]>[] methods, Metadata headers = null,
 455        DateTime? deadline = null,
 456        CancellationToken cancellationToken = default)
 1457    {
 1458        List<WatchRequest> requests = [];
 459
 5460        foreach (string key in keys)
 1461        {
 1462            WatchRequest request = new()
 1463            {
 1464                CreateRequest = new WatchCreateRequest { Key = ByteString.CopyFromUtf8(key) }
 1465            };
 1466            requests.Add(request);
 1467        }
 468
 1469        Watch(requests.ToArray(), methods, headers, deadline, cancellationToken);
 1470    }
 471
 472
 473    /// <summary>
 474    ///     Watches the specified key and passes the watch response to the method provided.
 475    /// </summary>
 476    /// <param name="key">Key to be watched</param>
 477    /// <param name="method">Method to which a watch response should be passed on</param>
 478    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 479    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 480    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 481    public Task WatchAsync(string key, Action<WatchResponse> method, Metadata headers = null,
 482        DateTime? deadline = null,
 1483        CancellationToken cancellationToken = default) => WatchAsync([key],
 1484        [method], headers, deadline, cancellationToken);
 485
 486    /// <summary>
 487    ///     Watches the specified key and passes the watch response to the methods provided.
 488    /// </summary>
 489    /// <param name="key">Key to be watched</param>
 490    /// <param name="methods">Methods to which a watch response should be passed on</param>
 491    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 492    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 493    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 494    public Task WatchAsync(string key, Action<WatchResponse>[] methods, Metadata headers = null,
 495        DateTime? deadline = null,
 496        CancellationToken cancellationToken = default) =>
 0497        WatchAsync([key], methods, headers, deadline, cancellationToken);
 498
 499
 500    /// <summary>
 501    ///     Watches the specified keys and passes the watch response to the method provided.
 502    /// </summary>
 503    /// <param name="keys">Keys to be watched</param>
 504    /// <param name="method">Method to which a watch response should be passed on</param>
 505    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 506    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 507    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 508    public Task WatchAsync(string[] keys, Action<WatchResponse> method, Metadata headers = null,
 509        DateTime? deadline = null,
 0510        CancellationToken cancellationToken = default) => WatchAsync(keys, [method],
 0511        headers, deadline, cancellationToken);
 512
 513    /// <summary>
 514    ///     Watches the specified keys and passes the watch response to the method provided.
 515    /// </summary>
 516    /// <param name="keys">Keys to be watched</param>
 517    /// <param name="methods">Methods to which a watch response should be passed on</param>
 518    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 519    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 520    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 521    public Task WatchAsync(string[] keys, Action<WatchResponse>[] methods, Metadata headers = null,
 522        DateTime? deadline = null,
 523        CancellationToken cancellationToken = default)
 1524    {
 1525        List<WatchRequest> requests = [];
 526
 5527        foreach (string key in keys)
 1528        {
 1529            WatchRequest request = new()
 1530            {
 1531                CreateRequest = new WatchCreateRequest
 1532                {
 1533                    Key = ByteString.CopyFromUtf8(key), ProgressNotify = true, PrevKv = true
 1534                }
 1535            };
 1536            requests.Add(request);
 1537        }
 538
 1539        return WatchAsync(requests.ToArray(), methods, headers, deadline, cancellationToken);
 1540    }
 541
 542    /// <summary>
 543    ///     Watches the specified key and passes the minimal watch events data to the method provided.
 544    /// </summary>
 545    /// <param name="key">Key to be watched</param>
 546    /// <param name="method">Method to which minimal watch events data should be passed on</param>
 547    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 548    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 549    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 550    public Task WatchAsync(string key, Action<WatchEvent[]> method, Metadata headers = null,
 551        DateTime? deadline = null,
 1552        CancellationToken cancellationToken = default) => WatchAsync([key],
 1553        [method], headers, deadline, cancellationToken);
 554
 555    /// <summary>
 556    ///     Watches the specified key and passes the minimal watch events data to the methods provided.
 557    /// </summary>
 558    /// <param name="key">Key to be watched</param>
 559    /// <param name="methods">Methods to which minimal watch events data should be passed on</param>
 560    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 561    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 562    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 563    public Task WatchAsync(string key, Action<WatchEvent[]>[] methods, Metadata headers = null,
 564        DateTime? deadline = null,
 565        CancellationToken cancellationToken = default) =>
 0566        WatchAsync([key], methods, headers, deadline, cancellationToken);
 567
 568    /// <summary>
 569    ///     Watches the specified keys and passes the minimal watch events data to the method provided.
 570    /// </summary>
 571    /// <param name="keys">Keys to be watched</param>
 572    /// <param name="method">Method to which minimal watch events data should be passed on</param>
 573    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 574    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 575    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 576    public Task WatchAsync(string[] keys, Action<WatchEvent[]> method, Metadata headers = null,
 577        DateTime? deadline = null,
 0578        CancellationToken cancellationToken = default) => WatchAsync(keys, [method],
 0579        headers, deadline, cancellationToken);
 580
 581    /// <summary>
 582    ///     Watches the specified keys and passes the minimal watch events data to the method provided.
 583    /// </summary>
 584    /// <param name="keys">Keys to be watched</param>
 585    /// <param name="methods">Methods to which minimal watch events data should be passed on</param>
 586    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 587    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 588    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 589    public Task WatchAsync(string[] keys, Action<WatchEvent[]>[] methods, Metadata headers = null,
 590        DateTime? deadline = null,
 591        CancellationToken cancellationToken = default)
 1592    {
 1593        List<WatchRequest> requests = [];
 594
 5595        foreach (string key in keys)
 1596        {
 1597            WatchRequest request = new()
 1598            {
 1599                CreateRequest = new WatchCreateRequest
 1600                {
 1601                    Key = ByteString.CopyFromUtf8(key), ProgressNotify = true, PrevKv = true
 1602                }
 1603            };
 1604            requests.Add(request);
 1605        }
 606
 1607        return WatchAsync(requests.ToArray(), methods, headers, deadline, cancellationToken);
 1608    }
 609
 610    #endregion
 611
 612    #region Watch Range of keys
 613
 614    /// <summary>
 615    ///     Watches the specified key range and passes the watch response to the method provided.
 616    /// </summary>
 617    /// <param name="path">Path to be watched</param>
 618    /// <param name="method">Method to which a watch response should be passed on</param>
 619    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 620    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 621    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 622    /// <returns>A watch ID that can be used to cancel the watch</returns>
 623    public long WatchRange(string path, Action<WatchResponse> method, Metadata headers = null,
 624        DateTime? deadline = null,
 625        CancellationToken cancellationToken = default)
 7626    {
 7627        WatchRequest request = new()
 7628        {
 7629            CreateRequest = new WatchCreateRequest
 7630            {
 7631                Key = GetStringByteForRangeRequests(path),
 7632                RangeEnd = ByteString.CopyFromUtf8(GetRangeEnd(path)),
 7633                ProgressNotify = true,
 7634                PrevKv = true
 7635            }
 7636        };
 637
 7638        return _watchManager.Watch(request, method, headers, deadline, cancellationToken);
 7639    }
 640
 641    /// <summary>
 642    ///     Watches the specified key range and passes the watch response to the methods provided.
 643    /// </summary>
 644    /// <param name="path">Path to be watched</param>
 645    /// <param name="methods">Methods to which a watch response should be passed on</param>
 646    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 647    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 648    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 649    /// <returns>A watch ID that can be used to cancel the watch</returns>
 650    public long WatchRange(string path, Action<WatchResponse>[] methods, Metadata headers = null,
 651        DateTime? deadline = null,
 652        CancellationToken cancellationToken = default)
 1653    {
 654        // Create a wrapper method that calls all the methods
 1655        Action<WatchResponse> wrapper = response =>
 1656        {
 7657            foreach (Action<WatchResponse> method in methods)
 2658            {
 2659                method(response);
 2660            }
 2661        };
 662
 1663        return WatchRange(path, wrapper, headers, deadline, cancellationToken);
 1664    }
 665
 666    /// <summary>
 667    ///     Watches the specified key range and passes the watch response to the method provided.
 668    /// </summary>
 669    /// <param name="paths">Paths to be watched</param>
 670    /// <param name="method">Method to which a watch response should be passed on</param>
 671    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 672    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 673    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 674    /// <returns>An array of watch IDs that can be used to cancel the watches</returns>
 675    public long[] WatchRange(string[] paths, Action<WatchResponse> method, Metadata headers = null,
 676        DateTime? deadline = null,
 677        CancellationToken cancellationToken = default)
 1678    {
 1679        long[] watchIds = new long[paths.Length];
 680
 6681        for (int i = 0; i < paths.Length; i++)
 2682        {
 2683            watchIds[i] = WatchRange(paths[i], method, headers, deadline, cancellationToken);
 2684        }
 685
 1686        return watchIds;
 1687    }
 688
 689    /// <summary>
 690    ///     Watches the specified key range and passes the watch response to the method provided.
 691    /// </summary>
 692    /// <param name="paths">Paths to be watched</param>
 693    /// <param name="methods">Methods to which a watch response should be passed on</param>
 694    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 695    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 696    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 697    /// <returns>An array of watch IDs that can be used to cancel the watches</returns>
 698    public long[] WatchRange(string[] paths, Action<WatchResponse>[] methods, Metadata headers = null,
 699        DateTime? deadline = null,
 700        CancellationToken cancellationToken = default)
 2701    {
 2702        if (paths.Length != methods.Length)
 1703        {
 1704            throw new ArgumentException("The number of paths must match the number of methods");
 705        }
 706
 1707        long[] watchIds = new long[paths.Length];
 708
 6709        for (int i = 0; i < paths.Length; i++)
 2710        {
 2711            watchIds[i] = WatchRange(paths[i], methods[i], headers, deadline, cancellationToken);
 2712        }
 713
 1714        return watchIds;
 1715    }
 716
 717    /// <summary>
 718    ///     Watches the specified key range and passes the watch response to the method provided asynchronously.
 719    /// </summary>
 720    /// <param name="path">Path to be watched</param>
 721    /// <param name="method">Method to which a watch response should be passed on</param>
 722    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 723    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 724    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 725    /// <returns>A task that completes with the watch ID</returns>
 726    public Task<long> WatchRangeAsync(string path, Action<WatchResponse> method, Metadata headers = null,
 727        DateTime? deadline = null,
 728        CancellationToken cancellationToken = default)
 6729    {
 6730        WatchRequest request = new()
 6731        {
 6732            CreateRequest = new WatchCreateRequest
 6733            {
 6734                Key = GetStringByteForRangeRequests(path),
 6735                RangeEnd = ByteString.CopyFromUtf8(GetRangeEnd(path)),
 6736                ProgressNotify = true,
 6737                PrevKv = true
 6738            }
 6739        };
 740
 6741        return _watchManager.WatchAsync(request, method, headers, deadline, cancellationToken);
 6742    }
 743
 744    /// <summary>
 745    ///     Watches the specified key range and passes the watch response to the methods provided asynchronously.
 746    /// </summary>
 747    /// <param name="path">Path to be watched</param>
 748    /// <param name="methods">Methods to which a watch response should be passed on</param>
 749    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 750    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 751    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 752    /// <returns>A task that completes with the watch ID</returns>
 753    public Task<long> WatchRangeAsync(string path, Action<WatchResponse>[] methods, Metadata headers = null,
 754        DateTime? deadline = null,
 755        CancellationToken cancellationToken = default)
 1756    {
 757        // Create a wrapper method that calls all the methods
 1758        Action<WatchResponse> wrapper = response =>
 1759        {
 7760            foreach (Action<WatchResponse> method in methods)
 2761            {
 2762                method(response);
 2763            }
 2764        };
 765
 1766        return WatchRangeAsync(path, wrapper, headers, deadline, cancellationToken);
 1767    }
 768
 769    /// <summary>
 770    ///     Watches the specified key range and passes the watch response to the method provided asynchronously.
 771    /// </summary>
 772    /// <param name="paths">Paths to be watched</param>
 773    /// <param name="method">Method to which a watch response should be passed on</param>
 774    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 775    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 776    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 777    /// <returns>A task that completes with an array of watch IDs</returns>
 778    public async Task<long[]> WatchRangeAsync(string[] paths, Action<WatchResponse> method, Metadata headers = null,
 779        DateTime? deadline = null,
 780        CancellationToken cancellationToken = default)
 1781    {
 1782        long[] watchIds = new long[paths.Length];
 783
 6784        for (int i = 0; i < paths.Length; i++)
 2785        {
 2786            watchIds[i] = await WatchRangeAsync(paths[i], method, headers, deadline, cancellationToken)
 2787                .ConfigureAwait(false);
 2788        }
 789
 1790        return watchIds;
 1791    }
 792
 793    /// <summary>
 794    ///     Watches the specified key range and passes the watch response to the method provided asynchronously.
 795    /// </summary>
 796    /// <param name="paths">Paths to be watched</param>
 797    /// <param name="methods">Methods to which a watch response should be passed on</param>
 798    /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
 799    /// <param name="deadline">An optional deadline for the call. The call will be canceled if the deadline is hit.</par
 800    /// <param name="cancellationToken">An optional token for canceling the call.</param>
 801    /// <returns>A task that completes with an array of watch IDs</returns>
 802    public async Task<long[]> WatchRangeAsync(string[] paths, Action<WatchResponse>[] methods, Metadata headers = null,
 803        DateTime? deadline = null,
 804        CancellationToken cancellationToken = default)
 2805    {
 2806        if (paths.Length != methods.Length)
 1807        {
 1808            throw new ArgumentException("The number of paths must match the number of methods");
 809        }
 810
 1811        long[] watchIds = new long[paths.Length];
 812
 6813        for (int i = 0; i < paths.Length; i++)
 2814        {
 2815            watchIds[i] = await WatchRangeAsync(paths[i], methods[i], headers, deadline, cancellationToken)
 2816                .ConfigureAwait(false);
 2817        }
 818
 1819        return watchIds;
 1820    }
 821
 822    #endregion
 823}

Methods/Properties

Authenticate(Etcdserverpb.AuthenticateRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<AuthenticateAsync()
AuthEnable(Etcdserverpb.AuthEnableRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<AuthEnableAsync()
AuthDisable(Etcdserverpb.AuthDisableRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<AuthDisableAsync()
UserAdd(Etcdserverpb.AuthUserAddRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<UserAddAsync()
UserGet(Etcdserverpb.AuthUserGetRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<UserGetAsync()
UserList(Etcdserverpb.AuthUserListRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<UserListAsync()
UserDelete(Etcdserverpb.AuthUserDeleteRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<UserDeleteAsync()
UserChangePassword(Etcdserverpb.AuthUserChangePasswordRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<UserChangePasswordAsync()
UserGrantRole(Etcdserverpb.AuthUserGrantRoleRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<UserGrantRoleAsync()
UserRevokeRole(Etcdserverpb.AuthUserRevokeRoleRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<UserRevokeRoleAsync()
RoleAdd(Etcdserverpb.AuthRoleAddRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<RoleAddAsync()
RoleGet(Etcdserverpb.AuthRoleGetRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<RoleGetAsync()
RoleList(Etcdserverpb.AuthRoleListRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<RoleListAsync()
RoleDelete(Etcdserverpb.AuthRoleDeleteRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<RoleDeleteAsync()
RoleGrantPermission(Etcdserverpb.AuthRoleGrantPermissionRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<RoleGrantPermissionAsync()
RoleRevokePermission(Etcdserverpb.AuthRoleRevokePermissionRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<RoleRevokePermissionAsync()
MemberAdd(Etcdserverpb.MemberAddRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<MemberAddAsync()
MemberRemove(Etcdserverpb.MemberRemoveRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<MemberRemoveAsync()
MemberUpdate(Etcdserverpb.MemberUpdateRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<MemberUpdateAsync()
MemberList(Etcdserverpb.MemberListRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<MemberListAsync()
Campaign(V3Electionpb.CampaignRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Campaign(System.String,System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<CampaignAsync()
<CampaignAsync()
Proclaim(V3Electionpb.ProclaimRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Proclaim(V3Electionpb.LeaderKey,System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<ProclaimAsync()
<ProclaimAsync()
Leader(V3Electionpb.LeaderRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Leader(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<LeaderAsync()
<LeaderAsync()
ObserveAsync()
ObserveAsync()
Resign(V3Electionpb.ResignRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Resign(V3Electionpb.LeaderKey,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<ResignAsync()
<ResignAsync()
Observe(V3Electionpb.LeaderRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Observe(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
GetConnection()
GetWatchManager()
CancelWatch(System.Int64)
CancelWatch(System.Int64[])
get_Username()
.ctor(Grpc.Core.CallInvoker)
.cctor()
.ctor(System.String,System.Int32,System.String,System.Action`1<Grpc.Net.Client.GrpcChannelOptions>,Grpc.Core.Interceptors.Interceptor[])
.ctor(System.String,System.Action`1<System.Net.Security.SslClientAuthenticationOptions>,System.Int32,System.String,System.Action`1<Grpc.Net.Client.GrpcChannelOptions>,Grpc.Core.Interceptors.Interceptor[])
.ctor(System.String,System.String,System.String,System.Int32,System.String,System.Action`1<Grpc.Net.Client.GrpcChannelOptions>,System.Nullable`1<System.TimeSpan>)
.ctor(dotnet_etcd.interfaces.IConnection,dotnet_etcd.interfaces.IWatchManager)
SetCredentials(System.String,System.String,System.Nullable`1<System.TimeSpan>)
ClearCredentials()
EnsureAuthenticationSupported()
RequestTokenAsync()
Dispose(System.Boolean)
Dispose()
Get(Etcdserverpb.RangeRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Get(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<GetAsync()
GetAsync()
GetVal(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
GetValAsync()
GetRange(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
GetRangeAsync()
GetRangeVal(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
GetRangeValAsync()
Put(Etcdserverpb.PutRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Put(System.String,System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<PutAsync()
PutAsync()
Delete(Etcdserverpb.DeleteRangeRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Delete(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<DeleteAsync()
DeleteAsync()
DeleteRange(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
DeleteRangeAsync()
Transaction(Etcdserverpb.TxnRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<TransactionAsync()
Compact(Etcdserverpb.CompactionRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<CompactAsync()
LeaseGrant(Etcdserverpb.LeaseGrantRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<LeaseGrantAsync()
LeaseRevoke(Etcdserverpb.LeaseRevokeRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<LeaseRevokeAsync()
LeaseKeepAlive(System.Threading.CancellationTokenSource,System.Int64,System.Int32,System.Nullable`1<System.Int32>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>)
LeaseKeepAlive()
<LeaseKeepAlive()
LeaseKeepAlive()
<LeaseKeepAlive()
LeaseKeepAlive()
<LeaseKeepAlive()
LeaseKeepAlive()
<LeaseKeepAlive()
LeaseKeepAlive()
<LeaseKeepAlive()
LeaseTimeToLive(Etcdserverpb.LeaseTimeToLiveRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<LeaseTimeToLiveAsync()
Lock(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Lock(V3Lockpb.LockRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
LockAsync()
LockAsync()
<LockAsync()
Unlock(System.String,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Unlock(V3Lockpb.UnlockRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
UnlockAsync()
UnlockAsync()
<UnlockAsync()
Alarm(Etcdserverpb.AlarmRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<AlarmAsync()
Status(Etcdserverpb.StatusRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<StatusAsync()
Defragment(Etcdserverpb.DefragmentRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<DefragmentAsync()
Hash(Etcdserverpb.HashRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<HashAsync()
HashKV(Etcdserverpb.HashKVRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<HashKVAsync()
Snapshot()
<Snapshot()
Snapshot()
<Snapshot()
MoveLeader(Etcdserverpb.MoveLeaderRequest,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
<MoveLeaderAsync()
RangeRespondToDictionary(Etcdserverpb.RangeResponse)
GetRangeEnd(System.String)
GetStringByteForRangeRequests(System.String)
CallEtcd(System.Func`2<dotnet_etcd.interfaces.IConnection,TResponse>)
CallEtcdAsync(System.Func`2<dotnet_etcd.interfaces.IConnection,System.Threading.Tasks.Task`1<TResponse>>)
CallEtcdAsync(System.Func`2<dotnet_etcd.interfaces.IConnection,System.Threading.Tasks.Task>)
WatchAsync()
WatchAsync(Etcdserverpb.WatchRequest[],System.Action`1<dotnet_etcd.WatchEvent[]>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(Etcdserverpb.WatchRequest[],System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(Etcdserverpb.WatchRequest[],System.Action`1<dotnet_etcd.WatchEvent[]>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(Etcdserverpb.WatchRequest,System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(Etcdserverpb.WatchRequest,System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync()
WatchAsync()
WatchAsync(Etcdserverpb.WatchRequest,System.Action`1<dotnet_etcd.WatchEvent[]>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(Etcdserverpb.WatchRequest,System.Action`1<dotnet_etcd.WatchEvent[]>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(Etcdserverpb.WatchRequest,System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(Etcdserverpb.WatchRequest,System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String,System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String,System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String[],System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String[],System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String,System.Action`1<dotnet_etcd.WatchEvent[]>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String,System.Action`1<dotnet_etcd.WatchEvent[]>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String[],System.Action`1<dotnet_etcd.WatchEvent[]>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
Watch(System.String[],System.Action`1<dotnet_etcd.WatchEvent[]>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String,System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String,System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String[],System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String[],System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String,System.Action`1<dotnet_etcd.WatchEvent[]>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String,System.Action`1<dotnet_etcd.WatchEvent[]>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String[],System.Action`1<dotnet_etcd.WatchEvent[]>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchAsync(System.String[],System.Action`1<dotnet_etcd.WatchEvent[]>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchRange(System.String,System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchRange(System.String,System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchRange(System.String[],System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchRange(System.String[],System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchRangeAsync(System.String,System.Action`1<Etcdserverpb.WatchResponse>,Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchRangeAsync(System.String,System.Action`1<Etcdserverpb.WatchResponse>[],Grpc.Core.Metadata,System.Nullable`1<System.DateTime>,System.Threading.CancellationToken)
WatchRangeAsync()
WatchRangeAsync()