|
| 1 | +import { LoggerService } from "@akashnetwork/logging"; |
| 2 | +import { singleton } from "tsyringe"; |
| 3 | + |
| 4 | +import { BillingConfig, InjectBillingConfig } from "@src/billing/providers"; |
| 5 | +import { UserWalletOutput, UserWalletRepository } from "@src/billing/repositories"; |
| 6 | +import { ManagedUserWalletService, RpcMessageService } from "@src/billing/services"; |
| 7 | +import { ErrorService } from "@src/core/services/error/error.service"; |
| 8 | +import { ProviderCleanupSummarizer } from "@src/deployment/lib/provider-cleanup-summarizer/provider-cleanup-summarizer"; |
| 9 | +import { DeploymentRepository } from "@src/deployment/repositories/deployment/deployment.repository"; |
| 10 | +import { TxSignerService } from "../tx-signer/tx-signer.service"; |
| 11 | + |
| 12 | +export interface ProviderCleanupParams { |
| 13 | + concurrency: number; |
| 14 | + providerAddress: string; |
| 15 | + dryRun: boolean; |
| 16 | +} |
| 17 | + |
| 18 | +@singleton() |
| 19 | +export class ProviderCleanupService { |
| 20 | + private readonly logger = LoggerService.forContext(ProviderCleanupService.name); |
| 21 | + |
| 22 | + constructor( |
| 23 | + @InjectBillingConfig() private readonly config: BillingConfig, |
| 24 | + private readonly userWalletRepository: UserWalletRepository, |
| 25 | + private readonly managedUserWalletService: ManagedUserWalletService, |
| 26 | + private readonly txSignerService: TxSignerService, |
| 27 | + private readonly deploymentRepository: DeploymentRepository, |
| 28 | + private readonly rpcMessageService: RpcMessageService, |
| 29 | + private readonly errorService: ErrorService |
| 30 | + ) {} |
| 31 | + |
| 32 | + async cleanup(options: ProviderCleanupParams) { |
| 33 | + const summary = new ProviderCleanupSummarizer(); |
| 34 | + await this.userWalletRepository.paginate({ query: { isTrialing: true }, limit: options.concurrency || 10 }, async wallets => { |
| 35 | + const cleanUpAllWallets = wallets.map(async wallet => { |
| 36 | + await this.errorService.execWithErrorHandler( |
| 37 | + { |
| 38 | + wallet, |
| 39 | + event: "PROVIDER_CLEAN_UP_ERROR", |
| 40 | + context: ProviderCleanupService.name |
| 41 | + }, |
| 42 | + () => this.cleanUpForWallet(wallet, options, summary) |
| 43 | + ); |
| 44 | + }); |
| 45 | + |
| 46 | + await Promise.all(cleanUpAllWallets); |
| 47 | + }); |
| 48 | + |
| 49 | + this.logger.info({ event: "PROVIDER_CLEAN_UP_SUMMARY", summary: summary.summarize(), dryRun: options.dryRun }); |
| 50 | + } |
| 51 | + |
| 52 | + private async cleanUpForWallet(wallet: UserWalletOutput, options: ProviderCleanupParams, summary: ProviderCleanupSummarizer) { |
| 53 | + const client = await this.txSignerService.getClientForAddressIndex(wallet.id); |
| 54 | + const deployments = await this.deploymentRepository.findDeploymentsForProvider({ |
| 55 | + owner: wallet.address, |
| 56 | + provider: options.providerAddress |
| 57 | + }); |
| 58 | + |
| 59 | + const closeAllWalletStaleDeployments = deployments.map(async deployment => { |
| 60 | + const message = this.rpcMessageService.getCloseDeploymentMsg(wallet.address, deployment.dseq); |
| 61 | + this.logger.info({ event: "PROVIDER_CLEAN_UP", params: { owner: wallet.address, dseq: deployment.dseq } }); |
| 62 | + |
| 63 | + try { |
| 64 | + if (!options.dryRun) { |
| 65 | + await client.signAndBroadcast([message]); |
| 66 | + this.logger.info({ event: "PROVIDER_CLEAN_UP_SUCCESS" }); |
| 67 | + } |
| 68 | + } catch (error) { |
| 69 | + if (error.message.includes("not allowed to pay fees")) { |
| 70 | + if (!options.dryRun) { |
| 71 | + await this.managedUserWalletService.authorizeSpending({ |
| 72 | + address: wallet.address, |
| 73 | + limits: { |
| 74 | + fees: this.config.FEE_ALLOWANCE_REFILL_AMOUNT |
| 75 | + } |
| 76 | + }); |
| 77 | + await client.signAndBroadcast([message]); |
| 78 | + this.logger.info({ event: "PROVIDER_CLEAN_UP_SUCCESS" }); |
| 79 | + } |
| 80 | + } else { |
| 81 | + throw error; |
| 82 | + } |
| 83 | + } finally { |
| 84 | + summary.inc("deploymentCount"); |
| 85 | + } |
| 86 | + }); |
| 87 | + |
| 88 | + await Promise.all(closeAllWalletStaleDeployments); |
| 89 | + } |
| 90 | +} |
0 commit comments