Skip to content

Commit 3642087

Browse files
author
Andrii Bondarchuk
committed
Refactor HOF scraper: add FixedSizeQueue, improve upserts
Introduce FixedSizeQueue<T> utility for tracking recent upsert results in the Everesting HOF scraper. Replace StoreData with UpsertActivities, returning detailed upsert outcomes (Created, Updated, Error) via new UpsertResult and UpsertStatus types. Update scraper logic to only stop when all recent upserts are successful updates, enhancing synchronization reliability. Improve logging for upsert operations.
1 parent 42e0c50 commit 3642087

File tree

2 files changed

+90
-14
lines changed

2 files changed

+90
-14
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System.Collections;
2+
3+
namespace FitSyncHub.Common.Collections;
4+
5+
public class FixedSizeQueue<T> : IEnumerable<T>, IReadOnlyCollection<T>, ICollection
6+
{
7+
private readonly Queue<T> _queue;
8+
9+
public FixedSizeQueue(int maxSize)
10+
{
11+
if (maxSize <= 0)
12+
{
13+
throw new ArgumentOutOfRangeException(nameof(maxSize), "Max size must be greater than zero.");
14+
}
15+
16+
_queue = new Queue<T>(maxSize);
17+
}
18+
19+
public void Enqueue(T item)
20+
{
21+
// Remove oldest if at capacity
22+
if (_queue.Count >= MaxSize)
23+
{
24+
_queue.Dequeue();
25+
}
26+
_queue.Enqueue(item);
27+
}
28+
29+
public void Enqueue(params ICollection<T> items)
30+
{
31+
if (items.Count > MaxSize)
32+
{
33+
throw new ArgumentOutOfRangeException(nameof(items), "Items length is greater than max size.");
34+
}
35+
36+
foreach (var item in items)
37+
{
38+
Enqueue(item);
39+
}
40+
}
41+
42+
public IEnumerator GetEnumerator() => _queue.GetEnumerator();
43+
void ICollection.CopyTo(Array array, int index) => (_queue as ICollection).CopyTo(array, index);
44+
45+
IEnumerator<T> IEnumerable<T>.GetEnumerator() => _queue.GetEnumerator();
46+
IEnumerator IEnumerable.GetEnumerator() => _queue.GetEnumerator();
47+
public int Count => _queue.Count;
48+
public int MaxSize => _queue.Capacity;
49+
bool ICollection.IsSynchronized => ((ICollection)_queue).IsSynchronized;
50+
object ICollection.SyncRoot => ((ICollection)_queue).IsSynchronized;
51+
}
52+

src/FitSyncHub.Functions/Functions/EverestingHOFScraperHttpTriggerFunction.cs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Text.Json;
55
using System.Text.Json.Serialization;
66
using System.Text.RegularExpressions;
7+
using FitSyncHub.Common.Collections;
78
using HtmlAgilityPack;
89
using Microsoft.AspNetCore.Http;
910
using Microsoft.AspNetCore.Mvc;
@@ -43,16 +44,12 @@ public async Task<IActionResult> Run(
4344
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "everesting-hof-scraper")] HttpRequest req,
4445
CancellationToken cancellationToken)
4546
{
46-
var lastSyncedDateTime = await GetLastSynchronizedDate(cancellationToken);
47-
48-
// do not know how HOF works, add this delta to be sure that we synced all
49-
// maybe need to increase days
50-
lastSyncedDateTime = lastSyncedDateTime.AddDays(-60);
51-
5247
const string BaseUrl = "https://hof.everesting.com/activities";
48+
var lastSyncedDateTime = await GetLastSynchronizedDate(cancellationToken);
5349

5450
var page = 1;
5551
int? totalPages = default;
52+
var latestUpsertResults = new FixedSizeQueue<UpsertResult>(5 * 5);
5653

5754
do
5855
{
@@ -73,12 +70,16 @@ public async Task<IActionResult> Run(
7370
totalPages = GetTotalPages(activitiesPortionJsonDocument);
7471
}
7572

76-
if (AllActiviesSynced(activitiesPortionJsonDocument, lastSyncedDateTime))
73+
var upsertResults = await UpsertActivities(activitiesPortionJsonDocument, cancellationToken);
74+
latestUpsertResults.Enqueue(upsertResults);
75+
76+
var allActiviesSynced = AllActiviesSynced(activitiesPortionJsonDocument, lastSyncedDateTime);
77+
if (allActiviesSynced
78+
&& latestUpsertResults.All(x => x.Error is null && x.Status == UpsertStatus.Updated)
79+
&& latestUpsertResults.Count == latestUpsertResults.MaxSize)
7780
{
7881
break;
7982
}
80-
81-
await StoreData(activitiesPortionJsonDocument, cancellationToken);
8283
}
8384
catch (Exception ex)
8485
{
@@ -200,7 +201,7 @@ private static JsonElement ParseActivitiesJsonFromFullScript(IEnumerable<string>
200201
private static int GetCurrentPage(JsonElement root) => root.GetProperty("currentPage").GetInt32();
201202
private static int GetTotalPages(JsonElement root) => root.GetProperty("totalPages").GetInt32();
202203

203-
private async Task StoreData(
204+
private async Task<List<UpsertResult>> UpsertActivities(
204205
JsonElement root,
205206
CancellationToken cancellationToken)
206207
{
@@ -229,27 +230,50 @@ private async Task StoreData(
229230
);
230231
}
231232

233+
var result = new List<UpsertResult>();
234+
232235
await foreach (var task in Task.WhenEach(tasks))
233236
{
234-
var result = await task;
235-
if (result.StatusCode == HttpStatusCode.OK)
237+
UpsertResult upsertResult;
238+
239+
var response = await task;
240+
if (response.StatusCode == HttpStatusCode.OK)
236241
{
237242
_logger.LogInformation("Updated item successfully.");
243+
upsertResult = new UpsertResult { Status = UpsertStatus.Updated };
238244
}
239-
else if (result.StatusCode == HttpStatusCode.Created)
245+
else if (response.StatusCode == HttpStatusCode.Created)
240246
{
241247
_logger.LogInformation("Created item successfully.");
248+
upsertResult = new UpsertResult { Status = UpsertStatus.Created };
242249
}
243250
else
244251
{
245-
_logger.LogError("Failed to upsert item. Status code: {StatusCode}", result.StatusCode);
252+
_logger.LogError("Failed to upsert item. Status code: {StatusCode}", response.StatusCode);
253+
upsertResult = new UpsertResult { Error = response.ErrorMessage };
246254
}
255+
256+
result.Add(upsertResult);
247257
}
258+
259+
return result;
248260
}
249261

250262
private record ActivityItemProjection
251263
{
252264
[JsonPropertyName("date")]
253265
public DateTime Date { get; init; }
254266
}
267+
268+
private record UpsertResult
269+
{
270+
public UpsertStatus? Status { get; init; }
271+
public string? Error { get; init; }
272+
}
273+
274+
private enum UpsertStatus
275+
{
276+
Created,
277+
Updated
278+
}
255279
}

0 commit comments

Comments
 (0)