Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions src/stellar/__tests__/stellar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,101 @@ describe('Stellar Integration - Unit Tests', () => {
expect(mockEvent.type).toBe('rebalance');
});
});

describe('Dead-Letter Queue - Persistent Storage', () => {
it('should create a DLQ entry with required fields', () => {
const event = {
type: 'deposit',
ledger: 12345,
txHash: 'tx-fail-001',
contractId: 'CVAULT',
};
const errorMsg = 'User not found';

const entry = {
id: 'dlq-id-1',
contractId: event.contractId,
txHash: event.txHash,
eventType: event.type,
ledger: event.ledger,
error: errorMsg,
payload: event,
status: 'PENDING' as const,
retryCount: 0,
createdAt: new Date(),
updatedAt: new Date(),
};

expect(entry.txHash).toBe('tx-fail-001');
expect(entry.status).toBe('PENDING');
expect(entry.retryCount).toBe(0);
expect(entry.contractId).toBe('CVAULT');
expect(entry.error).toBe(errorMsg);
});

it('should mark entry as RESOLVED after successful retry', () => {
let status: 'PENDING' | 'RETRIED' | 'RESOLVED' = 'PENDING';
let retryCount = 0;

// Simulate successful retry
retryCount++;
status = 'RESOLVED';

expect(status).toBe('RESOLVED');
expect(retryCount).toBe(1);
});

it('should mark entry as RETRIED after failed retry', () => {
let status: 'PENDING' | 'RETRIED' | 'RESOLVED' = 'PENDING';
let retryCount = 0;

// Simulate failed retry
retryCount++;
status = 'RETRIED';

expect(status).toBe('RETRIED');
expect(retryCount).toBe(1);
});

it('should only retry PENDING and RETRIED entries', () => {
const entries = [
{ id: '1', status: 'PENDING' as const },
{ id: '2', status: 'RETRIED' as const },
{ id: '3', status: 'RESOLVED' as const },
];

const retryable = entries.filter(
e => e.status === 'PENDING' || e.status === 'RETRIED'
);

expect(retryable.length).toBe(2);
expect(retryable.map(e => e.id)).toEqual(['1', '2']);
});

it('should trigger alert when queue size reaches threshold', () => {
const threshold = 50;
const sizes = [49, 50, 51];
const alerts = sizes.map(size => size >= threshold);

expect(alerts[0]).toBe(false); // 49 — no alert
expect(alerts[1]).toBe(true); // 50 — alert
expect(alerts[2]).toBe(true); // 51 — alert
});

it('should persist retry metadata across restarts', () => {
// Database-backed DLQ: all state lives in DB rows
const dbRecord = {
id: 'dlq-1',
retryCount: 3,
status: 'RETRIED' as const,
updatedAt: new Date(),
};

// After a restart, the same record is loaded from DB unchanged
const reloaded = { ...dbRecord };

expect(reloaded.retryCount).toBe(3);
expect(reloaded.status).toBe('RETRIED');
});
});
});
Loading