-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
BackupOperation.cs
153 lines (133 loc) · 6.89 KB
/
BackupOperation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Security.KeyVault.Administration.Models;
namespace Azure.Security.KeyVault.Administration
{
/// <summary>
/// A long-running operation for <see cref="KeyVaultBackupClient.StartBackup(Uri, string, CancellationToken)"/> or <see cref="KeyVaultBackupClient.StartBackupAsync(Uri, string, CancellationToken)"/>.
/// </summary>
public class BackupOperation : Operation<Uri>
{
/// <summary>
/// The number of seconds recommended by the service to delay before checking on completion status.
/// </summary>
private readonly int? _retryAfterSeconds;
private readonly KeyVaultBackupClient _client;
private Response _response;
private FullBackupDetailsInternal _value;
private readonly string _id;
/// <summary>
/// Creates an instance of a BackupOperation from a previously started operation. <see cref="UpdateStatus(CancellationToken)"/>, <see cref="UpdateStatusAsync(CancellationToken)"/>,
/// <see cref="WaitForCompletionAsync(CancellationToken)"/>, or <see cref="WaitForCompletionAsync(TimeSpan, CancellationToken)"/> must be called
/// to re-populate the details of this operation.
/// </summary>
/// <param name="id">The <see cref="Id" /> from a previous <see cref="BackupOperation" />.</param>
/// <param name="client">An instance of <see cref="KeyVaultBackupClient" />.</param>
/// <exception cref="ArgumentNullException"><paramref name="id"/> or <paramref name="client"/> is null.</exception>
public BackupOperation(string id, KeyVaultBackupClient client)
{
Argument.AssertNotNull(id, nameof(id));
Argument.AssertNotNull(client, nameof(client));
_client = client;
_id = id;
}
/// <summary>
/// Initializes a new instance of a BackupOperation.
/// </summary>
/// <param name="client">An instance of <see cref="KeyVaultBackupClient" />.</param>
/// <param name="response">The <see cref="ResponseWithHeaders{T, THeaders}" /> returned from <see cref="KeyVaultBackupClient.StartBackup(Uri, string, CancellationToken)"/> or <see cref="KeyVaultBackupClient.StartBackupAsync(Uri, string, CancellationToken)"/>.</param>
internal BackupOperation(KeyVaultBackupClient client, ResponseWithHeaders<ServiceFullBackupHeaders> response)
{
_client = client;
_response = response;
_retryAfterSeconds = response.Headers.RetryAfter;
_id = response.Headers.JobId() ?? throw new InvalidOperationException("The response does not contain an Id");
}
/// <summary>
/// Initializes a new instance of a BackupOperation for mocking purposes.
/// </summary>
/// <param name="value">The <see cref="FullBackupDetailsInternal" /> that will be returned from <see cref="Value" />.</param>
/// <param name="response">The <see cref="Response" /> that will be returned from <see cref="GetRawResponse" />.</param>
/// <param name="client">An instance of <see cref="KeyVaultBackupClient" />.</param>
internal BackupOperation(FullBackupDetailsInternal value, Response response, KeyVaultBackupClient client)
{
Argument.AssertNotNull(value, nameof(value));
Argument.AssertNotNull(response, nameof(response));
Argument.AssertNotNull(client, nameof(client));
_response = response;
_value = value;
_id = value.JobId;
_client = client;
}
/// <summary>
/// The start time of the restore operation.
/// </summary>
public DateTimeOffset? StartTime => _value?.StartTime;
/// <summary>
/// The end time of the restore operation.
/// </summary>
public DateTimeOffset? EndTime => _value?.EndTime;
/// <inheritdoc/>
public override string Id => _id;
/// <summary>
/// Gets the <see cref="FullBackupDetailsInternal"/> of the backup operation.
/// You should await <see cref="WaitForCompletionAsync(CancellationToken)"/> before attempting to use a key in this pending state.
/// </summary>
public override Uri Value
{
get
{
#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
if (!HasCompleted)
{
throw new InvalidOperationException("The operation is not complete.");
}
if (EndTime.HasValue && _value.Error != null)
{
throw new RequestFailedException($"{_value.Error.Message}\nInnerError: {_value.Error.InnerError}\nCode: {_value.Error.Code}");
}
#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
return new Uri(_value.AzureStorageBlobContainerUri);
}
}
/// <inheritdoc/>
public override bool HasCompleted => EndTime.HasValue;
/// <inheritdoc/>
public override bool HasValue => _response != null && _value?.Error == null && HasCompleted;
/// <inheritdoc/>
public override Response GetRawResponse() => _response;
/// <inheritdoc/>
public override Response UpdateStatus(CancellationToken cancellationToken = default)
{
if (!HasCompleted)
{
Response<FullBackupDetailsInternal> response = _client.GetBackupDetails(Id, cancellationToken);
_value = response.Value;
_response = response.GetRawResponse();
}
return GetRawResponse();
}
/// <inheritdoc/>
public override async ValueTask<Response> UpdateStatusAsync(CancellationToken cancellationToken = default)
{
if (!HasCompleted)
{
Response<FullBackupDetailsInternal> response = await _client.GetBackupDetailsAsync(Id, cancellationToken).ConfigureAwait(false);
_value = response.Value;
_response = response.GetRawResponse();
}
return GetRawResponse();
}
/// <inheritdoc/>
public override ValueTask<Response<Uri>> WaitForCompletionAsync(CancellationToken cancellationToken = default) =>
_retryAfterSeconds.HasValue ? this.DefaultWaitForCompletionAsync(TimeSpan.FromSeconds(_retryAfterSeconds.Value), cancellationToken) :
this.DefaultWaitForCompletionAsync(cancellationToken);
/// <inheritdoc/>
public override ValueTask<Response<Uri>> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken) =>
this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken);
}
}