WIP
This commit is contained in:
parent
54b057886c
commit
7fc1ae0650
204 changed files with 4345 additions and 134 deletions
104
PlanTempus.Core/Outbox/OutboxService.cs
Normal file
104
PlanTempus.Core/Outbox/OutboxService.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#nullable enable
|
||||
|
||||
using System.Data;
|
||||
using System.Text.Json;
|
||||
using Insight.Database;
|
||||
using PlanTempus.Core.Database;
|
||||
|
||||
namespace PlanTempus.Core.Outbox;
|
||||
|
||||
public class OutboxService(IDatabaseOperations databaseOperations) : IOutboxService
|
||||
{
|
||||
public async Task EnqueueAsync(string type, object payload, IDbConnection? connection = null, IDbTransaction? transaction = null)
|
||||
{
|
||||
var sql = @"
|
||||
INSERT INTO system.outbox (type, payload)
|
||||
VALUES (@Type, @Payload::jsonb)";
|
||||
|
||||
var parameters = new
|
||||
{
|
||||
Type = type,
|
||||
Payload = JsonSerializer.Serialize(payload)
|
||||
};
|
||||
|
||||
if (connection != null)
|
||||
{
|
||||
await connection.ExecuteSqlAsync(sql, parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
using var db = databaseOperations.CreateScope(nameof(OutboxService));
|
||||
await db.Connection.ExecuteSqlAsync(sql, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<OutboxMessage>> GetPendingAsync(int batchSize = 10)
|
||||
{
|
||||
using var db = databaseOperations.CreateScope(nameof(OutboxService));
|
||||
|
||||
var sql = @"
|
||||
UPDATE system.outbox
|
||||
SET status = 'processing'
|
||||
WHERE id IN (
|
||||
SELECT id FROM system.outbox
|
||||
WHERE status = 'pending'
|
||||
ORDER BY created_at
|
||||
LIMIT @BatchSize
|
||||
FOR UPDATE SKIP LOCKED
|
||||
)
|
||||
RETURNING id, type, payload, status, created_at, processed_at, retry_count, error_message";
|
||||
|
||||
var results = await db.Connection.QuerySqlAsync<OutboxMessageDto>(sql, new { BatchSize = batchSize });
|
||||
|
||||
return results.Select(r => new OutboxMessage
|
||||
{
|
||||
Id = r.Id,
|
||||
Type = r.Type,
|
||||
Payload = JsonSerializer.Deserialize<JsonElement>(r.Payload),
|
||||
Status = r.Status,
|
||||
CreatedAt = r.CreatedAt,
|
||||
ProcessedAt = r.ProcessedAt,
|
||||
RetryCount = r.RetryCount,
|
||||
ErrorMessage = r.ErrorMessage
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task MarkAsSentAsync(Guid id)
|
||||
{
|
||||
using var db = databaseOperations.CreateScope(nameof(OutboxService));
|
||||
|
||||
var sql = @"
|
||||
UPDATE system.outbox
|
||||
SET status = 'sent', processed_at = NOW()
|
||||
WHERE id = @Id";
|
||||
|
||||
await db.Connection.ExecuteSqlAsync(sql, new { Id = id });
|
||||
}
|
||||
|
||||
public async Task MarkAsFailedAsync(Guid id, string errorMessage)
|
||||
{
|
||||
using var db = databaseOperations.CreateScope(nameof(OutboxService));
|
||||
|
||||
var sql = @"
|
||||
UPDATE system.outbox
|
||||
SET status = 'failed',
|
||||
processed_at = NOW(),
|
||||
retry_count = retry_count + 1,
|
||||
error_message = @ErrorMessage
|
||||
WHERE id = @Id";
|
||||
|
||||
await db.Connection.ExecuteSqlAsync(sql, new { Id = id, ErrorMessage = errorMessage });
|
||||
}
|
||||
|
||||
private class OutboxMessageDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Type { get; set; } = "";
|
||||
public string Payload { get; set; } = "";
|
||||
public string Status { get; set; } = "";
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? ProcessedAt { get; set; }
|
||||
public int RetryCount { get; set; }
|
||||
public string? ErrorMessage { get; set; }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue