diff --git a/src/app/page.tsx b/src/app/page.tsx index 28e8839..2c0aac1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -187,7 +187,15 @@ export default async function HomePage() { {/* Recently traded */} {recentTrades.length > 0 && (
-

Recently traded

+

+ Recently traded + + Full feed โ†’ + +

{recentTrades.map(({ hashtag }) => hashtag && ( +
+ +

Trade Feed

+ ({total.toLocaleString()} trades) +
+ +
+
+ {trades.map((t) => ( +
+
+ + {t.type.replace('_', ' ')} + +
+
+ {t.user.isFund ? ( + ๐Ÿฆ + ) : null} + + {t.user.displayUsername ?? t.user.username} + + ยท + + #{t.hashtag!.displayTag} + +
+

+ {formatDistanceToNow(t.createdAt, { addSuffix: true })} +

+
+
+
+

{formatNumber(t.shares)} sh @ {formatCurrency(t.price)}

+

{formatCurrency(t.total)}

+ {(t.type === 'SELL_LONG' || t.type === 'SELL_SHORT') && ( +

{formatPnl(t.profit)}

+ )} +
+
+ ))} +
+
+ + {totalPages > 1 && ( +
+ {page > 1 && ( + + โ† Prev + + )} + Page {page} of {totalPages} + {page < totalPages && ( + + Next โ†’ + + )} +
+ )} +
+ ) +} diff --git a/src/worker/index.ts b/src/worker/index.ts index 04b8a4d..4a52063 100644 --- a/src/worker/index.ts +++ b/src/worker/index.ts @@ -238,13 +238,27 @@ for (const worker of [priceWorker, maintenanceWorker, schedulerWorker]) { // โ”€โ”€ Repeatable jobs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ async function setupRepeatableJobs() { + // Always wipe existing repeatable registrations first so that: + // - stale entries from old PRICE_UPDATE_INTERVAL_MINUTES values don't persist + // - jobs exhausted by BullMQ retry limits get rescheduled cleanly + const [existingScheduler, existingMaintenance] = await Promise.all([ + schedulerQueue.getRepeatableJobs(), + maintenanceQueue.getRepeatableJobs(), + ]) + await Promise.all([ + ...existingScheduler.map((j) => schedulerQueue.removeRepeatableByKey(j.key)), + ...existingMaintenance.map((j) => maintenanceQueue.removeRepeatableByKey(j.key)), + ]) + if (existingScheduler.length || existingMaintenance.length) { + console.log(`[worker] cleared ${existingScheduler.length} scheduler + ${existingMaintenance.length} maintenance repeatable(s)`) + } + // Price update sweep โ€” every N minutes await schedulerQueue.add( 'trigger-sweep', {}, { repeat: { every: UPDATE_INTERVAL_MIN * 60 * 1000 }, - jobId: 'price-sweep-repeatable', }, ) @@ -254,7 +268,6 @@ async function setupRepeatableJobs() { {}, { repeat: { pattern: '5 0 * * *' }, - jobId: 'daily-maintenance-repeatable', }, )