Skip to content

Commit c5d2921

Browse files
committed
chore(demo): broaden transient send failure detection
1 parent cf65f14 commit c5d2921

1 file changed

Lines changed: 36 additions & 27 deletions

File tree

examples/demo/Services/OneSignalApiService.cs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,13 @@ private async Task<bool> SendAsync(
123123

124124
const int maxAttempts = 5;
125125

126-
// Retry on `invalid_player_ids` to absorb the brief race where the
127-
// subscription has been created locally but is not yet visible to the
128-
// /notifications endpoint.
126+
// Retry while the OneSignal backend hasn't yet indexed the freshly
127+
// created subscription. The /notifications endpoint reports this race
128+
// in a few different shapes, all of which return HTTP 200:
129+
// {"errors":{"invalid_player_ids":[...]}}
130+
// {"id":"","errors":["All included players are not subscribed"]}
131+
// {"id":"","errors":[...]}
132+
// Treat any 200 response without a real notification id as transient.
129133
for (var attempt = 1; attempt <= maxAttempts; attempt++)
130134
{
131135
try
@@ -143,18 +147,15 @@ private async Task<bool> SendAsync(
143147
return false;
144148
}
145149

146-
var invalidIds = GetInvalidPlayerIds(responseJson);
147-
if (invalidIds.Count > 0)
150+
if (IsTransientSendFailure(responseJson))
148151
{
149152
if (attempt < maxAttempts)
150153
{
151154
var delayMs = 2000 * (1 << (attempt - 1));
152155
await Task.Delay(delayMs);
153156
continue;
154157
}
155-
Debug.WriteLine(
156-
$"Send notification failed: invalid_player_ids [{string.Join(", ", invalidIds)}]"
157-
);
158+
Debug.WriteLine($"Send notification failed: {responseJson}");
158159
return false;
159160
}
160161

@@ -170,38 +171,46 @@ private async Task<bool> SendAsync(
170171
return false;
171172
}
172173

173-
private static List<string> GetInvalidPlayerIds(string responseJson)
174+
private static bool IsTransientSendFailure(string responseJson)
174175
{
175-
var result = new List<string>();
176176
if (string.IsNullOrWhiteSpace(responseJson))
177-
return result;
177+
return false;
178178
try
179179
{
180180
using var doc = JsonDocument.Parse(responseJson);
181-
if (
182-
doc.RootElement.ValueKind == JsonValueKind.Object
183-
&& doc.RootElement.TryGetProperty("errors", out var errors)
184-
&& errors.ValueKind == JsonValueKind.Object
185-
&& errors.TryGetProperty("invalid_player_ids", out var invalidIds)
186-
&& invalidIds.ValueKind == JsonValueKind.Array
187-
)
181+
if (doc.RootElement.ValueKind != JsonValueKind.Object)
182+
return false;
183+
184+
var hasErrors = false;
185+
if (doc.RootElement.TryGetProperty("errors", out var errors))
188186
{
189-
foreach (var id in invalidIds.EnumerateArray())
187+
if (errors.ValueKind == JsonValueKind.Array)
190188
{
191-
if (id.ValueKind == JsonValueKind.String)
192-
{
193-
var s = id.GetString();
194-
if (!string.IsNullOrEmpty(s))
195-
result.Add(s);
196-
}
189+
hasErrors = errors.GetArrayLength() > 0;
197190
}
191+
else if (errors.ValueKind == JsonValueKind.Object)
192+
{
193+
var props = errors.EnumerateObject();
194+
hasErrors = props.MoveNext();
195+
}
196+
}
197+
198+
var missingId = true;
199+
if (
200+
doc.RootElement.TryGetProperty("id", out var id)
201+
&& id.ValueKind == JsonValueKind.String
202+
&& !string.IsNullOrEmpty(id.GetString())
203+
)
204+
{
205+
missingId = false;
198206
}
207+
208+
return hasErrors || missingId;
199209
}
200210
catch
201211
{
202-
// Ignore malformed bodies; treat as success since status was 2xx.
212+
return false;
203213
}
204-
return result;
205214
}
206215

207216
public async Task<UserData?> FetchUserAsync(string onesignalId)

0 commit comments

Comments
 (0)