|
2 | 2 | using System.Text; |
3 | 3 | using System.Text.Json; |
4 | 4 | using Stamps.ManagementPortal.Models; |
| 5 | +using Microsoft.Extensions.Logging; |
5 | 6 |
|
6 | 7 | namespace Stamps.ManagementPortal.Services; |
7 | 8 |
|
8 | | -public class GraphQLDataService(IHttpClientFactory httpClientFactory, IConfiguration config) : IDataService |
| 9 | +public class GraphQLDataService(IHttpClientFactory httpClientFactory, IConfiguration config, ILogger<GraphQLDataService> logger) : IDataService |
9 | 10 | { |
10 | 11 | private readonly IHttpClientFactory _httpClientFactory = httpClientFactory; |
11 | 12 | private readonly IConfiguration _config = config; |
| 13 | + private readonly ILogger<GraphQLDataService> _logger = logger; |
12 | 14 |
|
13 | 15 | private HttpClient Client => _httpClientFactory.CreateClient("GraphQL"); |
14 | 16 |
|
@@ -110,49 +112,71 @@ public async Task DeleteOperationAsync(string id, string partitionKey, Cancellat |
110 | 112 |
|
111 | 113 | private async Task<IReadOnlyList<T>> QueryAsync<T>(string query, string rootField, CancellationToken ct) |
112 | 114 | { |
| 115 | + _logger.LogInformation("Executing GraphQL query: {Query}", query); |
113 | 116 | var payload = new { query }; |
114 | 117 | using var req = new HttpRequestMessage(HttpMethod.Post, "") |
115 | 118 | { |
116 | 119 | Content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json") |
117 | 120 | }; |
118 | | - using var res = await Client.SendAsync(req, ct); |
119 | | - res.EnsureSuccessStatusCode(); |
120 | | - using var stream = await res.Content.ReadAsStreamAsync(ct); |
121 | | - using var doc = await JsonDocument.ParseAsync(stream, cancellationToken: ct); |
122 | | - // If GraphQL returned errors, surface them clearly |
123 | | - if (doc.RootElement.TryGetProperty("errors", out var errs) && errs.ValueKind == JsonValueKind.Array && errs.GetArrayLength() > 0) |
| 121 | + try |
124 | 122 | { |
125 | | - throw new HttpRequestException($"GraphQL errors: {errs}"); |
| 123 | + using var res = await Client.SendAsync(req, ct); |
| 124 | + res.EnsureSuccessStatusCode(); |
| 125 | + var responseContent = await res.Content.ReadAsStringAsync(ct); |
| 126 | + _logger.LogDebug("GraphQL response: {Response}", responseContent); |
| 127 | + using var doc = JsonDocument.Parse(responseContent); |
| 128 | + // If GraphQL returned errors, surface them clearly |
| 129 | + if (doc.RootElement.TryGetProperty("errors", out var errs) && errs.ValueKind == JsonValueKind.Array && errs.GetArrayLength() > 0) |
| 130 | + { |
| 131 | + _logger.LogError("GraphQL errors: {Errors}", errs.ToString()); |
| 132 | + throw new HttpRequestException($"GraphQL errors: {errs}"); |
| 133 | + } |
| 134 | + var data = doc.RootElement.GetProperty("data").GetProperty(rootField); |
| 135 | + var list = new List<T>(); |
| 136 | + foreach (var el in data.EnumerateArray()) |
| 137 | + { |
| 138 | + var obj = el.Deserialize<T>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); |
| 139 | + if (obj is not null) list.Add(obj); |
| 140 | + } |
| 141 | + return list; |
126 | 142 | } |
127 | | - var data = doc.RootElement.GetProperty("data").GetProperty(rootField); |
128 | | - var list = new List<T>(); |
129 | | - foreach (var el in data.EnumerateArray()) |
| 143 | + catch (Exception ex) |
130 | 144 | { |
131 | | - var obj = el.Deserialize<T>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); |
132 | | - if (obj is not null) list.Add(obj); |
| 145 | + _logger.LogError(ex, "Error executing GraphQL query: {Query}", query); |
| 146 | + throw; |
133 | 147 | } |
134 | | - return list; |
135 | 148 | } |
136 | 149 |
|
137 | 150 | private async Task<T> MutationAsync<T>(string query, object variables, string rootField, CancellationToken ct) |
138 | 151 | { |
| 152 | + _logger.LogInformation("Executing GraphQL mutation: {Query} with variables {Variables}", query, JsonSerializer.Serialize(variables)); |
139 | 153 | var payload = new { query, variables }; |
140 | 154 | using var req = new HttpRequestMessage(HttpMethod.Post, "") |
141 | 155 | { |
142 | 156 | Content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json") |
143 | 157 | }; |
144 | | - using var res = await Client.SendAsync(req, ct); |
145 | | - res.EnsureSuccessStatusCode(); |
146 | | - using var stream = await res.Content.ReadAsStreamAsync(ct); |
147 | | - using var doc = await JsonDocument.ParseAsync(stream, cancellationToken: ct); |
148 | | - if (doc.RootElement.TryGetProperty("errors", out var errs) && errs.ValueKind == JsonValueKind.Array && errs.GetArrayLength() > 0) |
| 158 | + try |
| 159 | + { |
| 160 | + using var res = await Client.SendAsync(req, ct); |
| 161 | + res.EnsureSuccessStatusCode(); |
| 162 | + var responseContent = await res.Content.ReadAsStringAsync(ct); |
| 163 | + _logger.LogDebug("GraphQL mutation response: {Response}", responseContent); |
| 164 | + using var doc = JsonDocument.Parse(responseContent); |
| 165 | + if (doc.RootElement.TryGetProperty("errors", out var errs) && errs.ValueKind == JsonValueKind.Array && errs.GetArrayLength() > 0) |
| 166 | + { |
| 167 | + _logger.LogError("GraphQL mutation errors: {Errors}", errs.ToString()); |
| 168 | + throw new HttpRequestException($"GraphQL errors: {errs}"); |
| 169 | + } |
| 170 | + var data = doc.RootElement.GetProperty("data").GetProperty(rootField); |
| 171 | + if (typeof(T) == typeof(object)) return default!; |
| 172 | + var result = data.Deserialize<T>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); |
| 173 | + return result!; |
| 174 | + } |
| 175 | + catch (Exception ex) |
149 | 176 | { |
150 | | - throw new HttpRequestException($"GraphQL errors: {errs}"); |
| 177 | + _logger.LogError(ex, "Error executing GraphQL mutation: {Query}", query); |
| 178 | + throw; |
151 | 179 | } |
152 | | - var data = doc.RootElement.GetProperty("data").GetProperty(rootField); |
153 | | - if (typeof(T) == typeof(object)) return default!; |
154 | | - var result = data.Deserialize<T>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); |
155 | | - return result!; |
156 | 180 | } |
157 | 181 |
|
158 | 182 | public async Task<bool> ReserveDomainAsync(string domain, string ownerTenantId, CancellationToken ct = default) |
|
0 commit comments