Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit 61685e6

Browse files
authored
Wrap fallible ORM functions in try/catch (#2745)
1 parent 81de102 commit 61685e6

File tree

1 file changed

+63
-32
lines changed
  • src/ApiService/ApiService/onefuzzlib/orm

1 file changed

+63
-32
lines changed

src/ApiService/ApiService/onefuzzlib/orm/Orm.cs

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,21 @@ public async IAsyncEnumerable<T> QueryAsync(string? filter = null) {
6464
/// Inserts the entity into table storage.
6565
/// If successful, updates the ETag of the passed-in entity.
6666
public async Task<ResultVoid<(HttpStatusCode Status, string Reason)>> Insert(T entity) {
67-
var tableClient = await GetTableClient(typeof(T).Name);
68-
var tableEntity = _entityConverter.ToTableEntity(entity);
69-
var response = await tableClient.AddEntityAsync(tableEntity);
67+
try {
68+
var tableClient = await GetTableClient(typeof(T).Name);
69+
var tableEntity = _entityConverter.ToTableEntity(entity);
70+
var response = await tableClient.AddEntityAsync(tableEntity);
7071

7172

72-
if (response.IsError) {
73-
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)response.Status, response.ReasonPhrase));
74-
} else {
75-
// update ETag on success
76-
entity.ETag = response.Headers.ETag;
77-
return ResultVoid<(HttpStatusCode, string)>.Ok();
73+
if (response.IsError) {
74+
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)response.Status, response.ReasonPhrase));
75+
} else {
76+
// update ETag on success
77+
entity.ETag = response.Headers.ETag;
78+
return ResultVoid<(HttpStatusCode, string)>.Ok();
79+
}
80+
} catch (RequestFailedException ex) {
81+
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)ex.Status, ex.Message));
7882
}
7983
}
8084

@@ -100,16 +104,20 @@ public async IAsyncEnumerable<T> QueryAsync(string? filter = null) {
100104
throw new ArgumentException("ETag must be set when updating an entity", nameof(entity));
101105
}
102106

103-
var tableClient = await GetTableClient(typeof(T).Name);
104-
var tableEntity = _entityConverter.ToTableEntity(entity);
107+
try {
108+
var tableClient = await GetTableClient(typeof(T).Name);
109+
var tableEntity = _entityConverter.ToTableEntity(entity);
105110

106-
var response = await tableClient.UpdateEntityAsync(tableEntity, entity.ETag.Value);
107-
if (response.IsError) {
108-
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)response.Status, response.ReasonPhrase));
109-
} else {
110-
// update ETag on success
111-
entity.ETag = response.Headers.ETag;
112-
return ResultVoid<(HttpStatusCode, string)>.Ok();
111+
var response = await tableClient.UpdateEntityAsync(tableEntity, entity.ETag.Value);
112+
if (response.IsError) {
113+
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)response.Status, response.ReasonPhrase));
114+
} else {
115+
// update ETag on success
116+
entity.ETag = response.Headers.ETag;
117+
return ResultVoid<(HttpStatusCode, string)>.Ok();
118+
}
119+
} catch (RequestFailedException ex) {
120+
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)ex.Status, ex.Message));
113121
}
114122
}
115123

@@ -127,13 +135,17 @@ public async Task<TableClient> GetTableClient(string table, ResourceIdentifier?
127135
}
128136

129137
public async Task<ResultVoid<(HttpStatusCode Status, string Reason)>> Delete(T entity) {
130-
var tableClient = await GetTableClient(typeof(T).Name);
131-
var tableEntity = _entityConverter.ToTableEntity(entity);
132-
var response = await tableClient.DeleteEntityAsync(tableEntity.PartitionKey, tableEntity.RowKey);
133-
if (response.IsError) {
134-
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)response.Status, response.ReasonPhrase));
135-
} else {
136-
return ResultVoid<(HttpStatusCode, string)>.Ok();
138+
try {
139+
var tableClient = await GetTableClient(typeof(T).Name);
140+
var tableEntity = _entityConverter.ToTableEntity(entity);
141+
var response = await tableClient.DeleteEntityAsync(tableEntity.PartitionKey, tableEntity.RowKey);
142+
if (response.IsError) {
143+
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)response.Status, response.ReasonPhrase));
144+
} else {
145+
return ResultVoid<(HttpStatusCode, string)>.Ok();
146+
}
147+
} catch (RequestFailedException ex) {
148+
return ResultVoid<(HttpStatusCode, string)>.Error(((HttpStatusCode)ex.Status, ex.Message));
137149
}
138150
}
139151

@@ -150,13 +162,32 @@ public IAsyncEnumerable<T> SearchByTimeRange(DateTimeOffset min, DateTimeOffset
150162
return QueryAsync(Query.TimeRange(min, max));
151163
}
152164

153-
public async Task<List<ResultVoid<(int, string)>>> BatchOperation(IAsyncEnumerable<T> entities, TableTransactionActionType actionType) {
154-
var tableClient = await GetTableClient(typeof(T).Name);
155-
var transactions = await entities.Select(e => new TableTransactionAction(actionType, _entityConverter.ToTableEntity(e))).ToListAsync();
156-
var responses = await tableClient.SubmitTransactionAsync(transactions);
157-
return responses.Value.Select(response =>
158-
response.IsError ? ResultVoid<(int, string)>.Error((response.Status, response.ReasonPhrase)) : ResultVoid<(int, string)>.Ok()
159-
).ToList();
165+
public async Task<ResultVoid<(int statusCode, string reason, int? failedTransactionIndex)>> BatchOperation(IAsyncEnumerable<T> entities, TableTransactionActionType actionType) {
166+
try {
167+
var tableClient = await GetTableClient(typeof(T).Name);
168+
var transactions = await entities.Select(e => new TableTransactionAction(actionType, _entityConverter.ToTableEntity(e))).ToListAsync();
169+
var responses = await tableClient.SubmitTransactionAsync(transactions);
170+
var wrappingResponse = responses.GetRawResponse();
171+
if (wrappingResponse.IsError) {
172+
return ResultVoid<(int, string, int?)>.Error((wrappingResponse.Status, wrappingResponse.ReasonPhrase, null));
173+
}
174+
175+
var subTransactionFailures = responses.Value.Where(response => response.IsError);
176+
if (subTransactionFailures.Any()) {
177+
var failedTransaction = subTransactionFailures.First();
178+
var failedTransactionIndex = responses.Value.ToList().IndexOf(failedTransaction);
179+
return ResultVoid<(int, string, int?)>.Error((failedTransaction.Status, failedTransaction.ReasonPhrase, failedTransactionIndex));
180+
}
181+
182+
return ResultVoid<(int, string, int?)>.Ok();
183+
} catch (RequestFailedException ex) {
184+
int? failedTransactionIndex = null;
185+
if (ex is TableTransactionFailedException ttfex) {
186+
failedTransactionIndex = ttfex.FailedTransactionActionIndex;
187+
}
188+
189+
return ResultVoid<(int, string, int?)>.Error((ex.Status, ex.Message, failedTransactionIndex));
190+
}
160191
}
161192

162193

0 commit comments

Comments
 (0)