feat: add recurring places and transaction pagination
Build MoneyMap image / build-and-push (push) Failing after 4s

This commit is contained in:
aj
2026-08-17 06:42:08 -04:00
parent 2356b7d5c9
commit 1cc0a355f2
175 changed files with 34411 additions and 34039 deletions
+56 -56
View File
@@ -1,56 +1,56 @@
using System.Threading.Channels;
namespace MoneyMap.Services
{
public interface IReceiptParseQueue
{
ValueTask EnqueueAsync(long receiptId, CancellationToken ct = default);
ValueTask EnqueueManyAsync(IEnumerable<long> receiptIds, CancellationToken ct = default);
ValueTask<long> DequeueAsync(CancellationToken ct);
int QueueLength { get; }
long? CurrentlyProcessingId { get; }
void SetCurrentlyProcessing(long? receiptId);
}
public class ReceiptParseQueue : IReceiptParseQueue
{
private readonly Channel<long> _channel = Channel.CreateUnbounded<long>(
new UnboundedChannelOptions { SingleReader = true });
private long _currentlyProcessingId;
public int QueueLength => _channel.Reader.Count;
public long? CurrentlyProcessingId
{
get
{
var val = Interlocked.Read(ref _currentlyProcessingId);
return val == 0 ? null : val;
}
}
public void SetCurrentlyProcessing(long? receiptId)
{
Interlocked.Exchange(ref _currentlyProcessingId, receiptId ?? 0);
}
public async ValueTask EnqueueAsync(long receiptId, CancellationToken ct = default)
{
await _channel.Writer.WriteAsync(receiptId, ct);
}
public async ValueTask EnqueueManyAsync(IEnumerable<long> receiptIds, CancellationToken ct = default)
{
foreach (var id in receiptIds)
{
await _channel.Writer.WriteAsync(id, ct);
}
}
public async ValueTask<long> DequeueAsync(CancellationToken ct)
{
return await _channel.Reader.ReadAsync(ct);
}
}
}
using System.Threading.Channels;
namespace MoneyMap.Services
{
public interface IReceiptParseQueue
{
ValueTask EnqueueAsync(long receiptId, CancellationToken ct = default);
ValueTask EnqueueManyAsync(IEnumerable<long> receiptIds, CancellationToken ct = default);
ValueTask<long> DequeueAsync(CancellationToken ct);
int QueueLength { get; }
long? CurrentlyProcessingId { get; }
void SetCurrentlyProcessing(long? receiptId);
}
public class ReceiptParseQueue : IReceiptParseQueue
{
private readonly Channel<long> _channel = Channel.CreateUnbounded<long>(
new UnboundedChannelOptions { SingleReader = true });
private long _currentlyProcessingId;
public int QueueLength => _channel.Reader.Count;
public long? CurrentlyProcessingId
{
get
{
var val = Interlocked.Read(ref _currentlyProcessingId);
return val == 0 ? null : val;
}
}
public void SetCurrentlyProcessing(long? receiptId)
{
Interlocked.Exchange(ref _currentlyProcessingId, receiptId ?? 0);
}
public async ValueTask EnqueueAsync(long receiptId, CancellationToken ct = default)
{
await _channel.Writer.WriteAsync(receiptId, ct);
}
public async ValueTask EnqueueManyAsync(IEnumerable<long> receiptIds, CancellationToken ct = default)
{
foreach (var id in receiptIds)
{
await _channel.Writer.WriteAsync(id, ct);
}
}
public async ValueTask<long> DequeueAsync(CancellationToken ct)
{
return await _channel.Reader.ReadAsync(ct);
}
}
}