80 lines
2.5 KiB
C#
80 lines
2.5 KiB
C#
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using UtopiaCanteenSystem.Data;
|
|
using UtopiaCanteenSystem.Models;
|
|
using System.Net.Http;
|
|
|
|
namespace UtopiaCanteenSystem.Services;
|
|
|
|
/// <summary>
|
|
/// Scheduled sync: fetches unsynced ScanRecords, POSTs them to the configured API,
|
|
/// and deletes uploaded records from local SQLite on success.
|
|
/// </summary>
|
|
public class SyncService : ISyncService
|
|
{
|
|
private readonly IDbContextFactory<AppDbContext> _dbFactory;
|
|
private readonly IConfigService _configService;
|
|
private static readonly HttpClient HttpClient = new();
|
|
|
|
public SyncService(IDbContextFactory<AppDbContext> dbFactory, IConfigService configService)
|
|
{
|
|
_dbFactory = dbFactory;
|
|
_configService = configService;
|
|
}
|
|
|
|
public async Task SyncNowAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
var endpoint = _configService.GetSyncApiEndpoint();
|
|
if (string.IsNullOrWhiteSpace(endpoint))
|
|
return;
|
|
|
|
List<ScanRecord> toSync;
|
|
using (var db = _dbFactory.CreateDbContext())
|
|
{
|
|
toSync = await db.ScanRecords
|
|
.Where(r => !r.IsSynced)
|
|
.OrderBy(r => r.ScanTime)
|
|
.ToListAsync(cancellationToken)
|
|
.ConfigureAwait(false);
|
|
}
|
|
|
|
if (toSync.Count == 0)
|
|
return;
|
|
|
|
var payload = toSync.Select(r => new
|
|
{
|
|
r.Id,
|
|
r.CardId,
|
|
ScanTime = r.ScanTime,
|
|
r.IsSynced
|
|
}).ToList();
|
|
|
|
try
|
|
{
|
|
var response = await HttpClient
|
|
.PostAsJsonAsync(endpoint, payload, cancellationToken: cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
return;
|
|
|
|
var ids = toSync.Select(r => r.Id).ToList();
|
|
using (var db = _dbFactory.CreateDbContext())
|
|
{
|
|
var records = await db.ScanRecords
|
|
.Where(r => ids.Contains(r.Id))
|
|
.ToListAsync(cancellationToken)
|
|
.ConfigureAwait(false);
|
|
// On successful upload, delete uploaded scan records from local SQLite.
|
|
db.ScanRecords.RemoveRange(records);
|
|
await db.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Leave records intact; will retry on next run
|
|
}
|
|
}
|
|
}
|