fix: widen rents.usd_amount column, add webhook alias, silence cron spam
- Migration to ALTER rents.usd_amount from numeric(5,2) to numeric(15,2) which was causing "numeric field overflow" 500 errors when saving rental prices >= 1000 sats (e.g. 1200 sats) - Also widen season_rents.usd_amount for consistency - Add /webhooks/btcpay route alias (BTCPay was posting to /btcpay but the endpoint was /btcpay-webhook, causing 404s on payment callbacks) - Skip ECS autoscaling cron when TRANSCODING_API_URL is not set (eliminates "security token invalid" error spam every minute) - Reduce payment cron from EVERY_MINUTE to EVERY_10_MINUTES to avoid 429 rate limiting on the BTC price API - Bump API CACHEBUST to 10 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Widen the usd_amount columns in rents and season_rents tables.
|
||||||
|
*
|
||||||
|
* The original migration (1711564180593) created rents.usd_amount as
|
||||||
|
* numeric(5,2), which caps at 999.99. Rental prices are stored in
|
||||||
|
* satoshis (e.g. 1200 sats) and easily exceed 999. The entity definition
|
||||||
|
* specifies precision 15, scale 2 — this migration aligns the database.
|
||||||
|
*
|
||||||
|
* season_rents.usd_amount (created in 1755016652731) has the same
|
||||||
|
* narrow precision and is updated here for consistency.
|
||||||
|
*/
|
||||||
|
export class WidenUsdAmountColumns1776300000000 implements MigrationInterface {
|
||||||
|
name = 'WidenUsdAmountColumns1776300000000';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "rents" ALTER COLUMN "usd_amount" TYPE numeric(15,2)`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_rents" ALTER COLUMN "usd_amount" TYPE numeric(15,2)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "rents" ALTER COLUMN "usd_amount" TYPE numeric(5,2)`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_rents" ALTER COLUMN "usd_amount" TYPE numeric(5,2)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -159,7 +159,7 @@ export class PaymentService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Cron(CronExpression.EVERY_MINUTE)
|
@Cron(CronExpression.EVERY_10_MINUTES)
|
||||||
async handlePaymentsCron() {
|
async handlePaymentsCron() {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.handlePayment('watch'),
|
this.handlePayment('watch'),
|
||||||
|
|||||||
@@ -102,10 +102,12 @@ export class TranscodingServerService {
|
|||||||
Logger.log(`Auto Scaling group scaled to ${desiredCount} instances`);
|
Logger.log(`Auto Scaling group scaled to ${desiredCount} instances`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the autoscaling logic every hour
|
// Run the autoscaling logic every hour (AWS ECS only).
|
||||||
|
// Skip when using the local FFmpeg worker (no TRANSCODING_API_URL).
|
||||||
@Cron(CronExpression.EVERY_MINUTE)
|
@Cron(CronExpression.EVERY_MINUTE)
|
||||||
async autoscaleEcsService() {
|
async autoscaleEcsService() {
|
||||||
if (process.env.ENVIRONMENT !== 'production') return;
|
if (process.env.ENVIRONMENT !== 'production') return;
|
||||||
|
if (!process.env.TRANSCODING_API_URL) return;
|
||||||
try {
|
try {
|
||||||
const queueSize = await this.getQueueSize();
|
const queueSize = await this.getQueueSize();
|
||||||
const currentTaskCount = await this.describeService(
|
const currentTaskCount = await this.describeService(
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import type { BTCPayWebhookEvent } from 'src/payment/providers/dto/btcpay/btcpay
|
|||||||
export class WebhooksController {
|
export class WebhooksController {
|
||||||
constructor(private readonly webhooksService: WebhooksService) {}
|
constructor(private readonly webhooksService: WebhooksService) {}
|
||||||
|
|
||||||
|
// Accept both /webhooks/btcpay-webhook (original) and /webhooks/btcpay
|
||||||
|
// so the webhook works regardless of which URL is configured in BTCPay.
|
||||||
@Post('btcpay-webhook')
|
@Post('btcpay-webhook')
|
||||||
@UseGuards(BTCPayGuard)
|
@UseGuards(BTCPayGuard)
|
||||||
async btcpayPayment(@Body() body: BTCPayWebhookEvent) {
|
async btcpayPayment(@Body() body: BTCPayWebhookEvent) {
|
||||||
@@ -22,4 +24,10 @@ export class WebhooksController {
|
|||||||
throw new BadRequestException(error.message);
|
throw new BadRequestException(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('btcpay')
|
||||||
|
@UseGuards(BTCPayGuard)
|
||||||
|
async btcpayPaymentAlias(@Body() body: BTCPayWebhookEvent) {
|
||||||
|
return this.btcpayPayment(body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ services:
|
|||||||
context: ./backend
|
context: ./backend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
CACHEBUST: "9"
|
CACHEBUST: "10"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
# ── Core ─────────────────────────────────────────────
|
# ── Core ─────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user