From 2974b542fa9242919ef358e4e25d9c5c17420338 Mon Sep 17 00:00:00 2001 From: Dread Date: Sat, 4 Jul 2026 09:14:54 -0400 Subject: [PATCH] fix(cron): gate LND maintenance tasks behind cronConfig.lndTasksEnabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cron server unconditionally ran upstream galoy's LND/bitcoin maintenance tasks (rebalancingInternalChannels, updateEscrows, pending LN invoice/payment updates, LnPayments sync, routing revenues, legacy onchain receipts, LND payment cleanup) plus checkAllLndHealth and activateLndHealthCheck. Flash is IBEX-custodial with no LND nodes, so deleteLndPaymentsBefore2Months throws OffChainServiceUnavailableError on every run — one failed task exits 99, so the daily k8s Job has been crash-looping (masked until now by the chart's missing -c configPath, fixed in charts 3.2.15). Add cronConfig.lndTasksEnabled (schema default true — upstream parity; legacy configs without the key validate and behave unchanged, verified through the real loader) and gate the LND task group and both health checkers behind it. With it false, the cron runs exactly the tasks that apply to Flash: mongo expiry cleanup (deleteExpiredPaymentFlows, deleteExpiredInvoices) and Bridge↔IBEX reconciliation (already self-gated on BridgeConfig.enabled). rebalance/swapOut keep their existing config gates. Deployments follow-up: set cronConfig.lndTasksEnabled=false in the chart config once this image ships. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/config/schema.ts | 5 +++++ src/config/schema.types.d.ts | 1 + src/config/types.d.ts | 1 + src/servers/cron.ts | 42 +++++++++++++++++++++++++----------- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/config/schema.ts b/src/config/schema.ts index ae2a44faa..4a08e99bb 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -579,12 +579,17 @@ export const configSchema = { properties: { rebalanceEnabled: { type: "boolean" }, swapEnabled: { type: "boolean" }, + // Gates the upstream-galoy LND/bitcoin maintenance tasks in the cron + // server. Flash runs IBEX-custodial with no LND, so deployments set + // this false; defaults true for upstream parity. + lndTasksEnabled: { type: "boolean", default: true }, }, required: ["rebalanceEnabled", "swapEnabled"], additionalProperties: false, default: { rebalanceEnabled: true, swapEnabled: true, + lndTasksEnabled: true, }, }, captcha: { diff --git a/src/config/schema.types.d.ts b/src/config/schema.types.d.ts index eebc3b59f..d75a82fb2 100644 --- a/src/config/schema.types.d.ts +++ b/src/config/schema.types.d.ts @@ -203,6 +203,7 @@ type YamlSchema = { cronConfig: { rebalanceEnabled: boolean swapEnabled: boolean + lndTasksEnabled: boolean } captcha: { mandatory: boolean diff --git a/src/config/types.d.ts b/src/config/types.d.ts index 0052969f5..4e601dac5 100644 --- a/src/config/types.d.ts +++ b/src/config/types.d.ts @@ -8,6 +8,7 @@ type Levels = number[] type CronConfig = { rebalanceEnabled: boolean swapEnabled: boolean + lndTasksEnabled: boolean } type CaptchaConfig = { diff --git a/src/servers/cron.ts b/src/servers/cron.ts index fe773cf42..b08488029 100644 --- a/src/servers/cron.ts +++ b/src/servers/cron.ts @@ -91,29 +91,45 @@ const reconcileBridgeWithdrawalsJob = async () => { const main = async () => { console.log("cronjob started") const start = new Date() - await checkAllLndHealth() const cronConfig = getCronConfig() + + // Flash runs IBEX-custodial with no LND nodes, so the upstream-galoy + // LND/bitcoin maintenance tasks have nothing to operate on — worse, the + // ones that require a reachable node throw OffChainServiceUnavailableError, + // failing the whole run (exit 99 → CrashLoopBackOff on the k8s Job). + // lndTasksEnabled (default true, for upstream parity) lets deployments + // without LND run only the tasks that apply: mongo expiry cleanup and + // Bridge↔IBEX reconciliation. + if (cronConfig.lndTasksEnabled) { + await checkAllLndHealth() + } + const results: Array = [] const mongoose = await setupMongoConnection() const tasks = [ - // bitcoin related tasks - rebalancingInternalChannels, - updateEscrows, - updatePendingLightningInvoices, - updatePendingLightningPayments, - updateLnPaymentsCollection, - updateRoutingRevenues, - updateLegacyOnChainReceipt, + // bitcoin/LND tasks — upstream galoy; require LND to do anything useful + ...(cronConfig.lndTasksEnabled + ? [ + rebalancingInternalChannels, + updateEscrows, + updatePendingLightningInvoices, + updatePendingLightningPayments, + updateLnPaymentsCollection, + updateRoutingRevenues, + updateLegacyOnChainReceipt, + ] + : []), ...(cronConfig.rebalanceEnabled ? [rebalance] : []), ...(cronConfig.swapEnabled ? [swapOutJob] : []), reconcileBridgeDepositsJob, reconcileBridgeWithdrawalsJob, deleteExpiredPaymentFlows, deleteExpiredInvoices, - deleteLndPaymentsBefore2Months, - deleteFailedPaymentsAttemptAllLnds, + ...(cronConfig.lndTasksEnabled + ? [deleteLndPaymentsBefore2Months, deleteFailedPaymentsAttemptAllLnds] + : []), ] const PROCESS_KILL_EVENTS = ["SIGTERM", "SIGINT"] @@ -198,7 +214,9 @@ const main = async () => { } try { - activateLndHealthCheck() + if (getCronConfig().lndTasksEnabled) { + activateLndHealthCheck() + } main() } catch (err) { logger.warn({ err }, "error in the cron job")