diff --git a/src/resource-rental/rental.module.ts b/src/resource-rental/rental.module.ts index 0562005e0..ae85790ba 100644 --- a/src/resource-rental/rental.module.ts +++ b/src/resource-rental/rental.module.ts @@ -6,8 +6,18 @@ import { StorageProvider } from "../shared/storage"; import { Logger } from "../shared/utils"; import { ResourceRental, ResourceRentalOptions } from "./resource-rental"; import { ResourceRentalPool, ResourceRentalPoolOptions } from "./resource-rental-pool"; +import { EventEmitter } from "eventemitter3"; + +export interface ResourceRentalModuleEvents { + /** Emitted when ResourceRenatl is successfully created */ + resourceRentalCreated: (agreement: Agreement) => void; + + /** Emitted when ResourceRenatlPool is successfully created */ + resourceRentalPoolCreated: () => void; +} export interface RentalModule { + events: EventEmitter; /** * Factory that creates a new resource rental that's fully configured. * This method will also create the payment process for the agreement. @@ -25,6 +35,7 @@ export interface RentalModule { } export class RentalModuleImpl implements RentalModule { + events = new EventEmitter(); constructor( private readonly deps: { marketModule: MarketModule; @@ -51,6 +62,7 @@ export class RentalModuleImpl implements RentalModule { this.deps.logger.child("resource-rental"), options, ); + this.events.emit("resourceRentalCreated", rental.agreement); return rental; } @@ -59,7 +71,7 @@ export class RentalModuleImpl implements RentalModule { allocation: Allocation, options?: ResourceRentalPoolOptions, ): ResourceRentalPool { - return new ResourceRentalPool({ + const pool = new ResourceRentalPool({ allocation, rentalModule: this, marketModule: this.deps.marketModule, @@ -70,5 +82,7 @@ export class RentalModuleImpl implements RentalModule { network: options?.network, poolSize: options?.poolSize, }); + this.events.emit("resourceRentalPoolCreated"); + return pool; } } diff --git a/src/resource-rental/resource-rental.ts b/src/resource-rental/resource-rental.ts index a31595890..1fdacd19a 100644 --- a/src/resource-rental/resource-rental.ts +++ b/src/resource-rental/resource-rental.ts @@ -2,7 +2,7 @@ import { Agreement } from "../market/agreement/agreement"; import { AgreementPaymentProcess, PaymentProcessOptions } from "../payment/agreement_payment_process"; import { createAbortSignalFromTimeout, Logger } from "../shared/utils"; import { waitForCondition } from "../shared/utils/wait"; -import { ActivityModule, ExeUnit, ExeUnitOptions } from "../activity"; +import { Activity, ActivityModule, ExeUnit, ExeUnitOptions } from "../activity"; import { StorageProvider } from "../shared/storage"; import { EventEmitter } from "eventemitter3"; import { NetworkNode } from "../network"; @@ -11,10 +11,17 @@ import { MarketModule } from "../market"; import { GolemAbortError, GolemTimeoutError, GolemUserError } from "../shared/error/golem-error"; export interface ResourceRentalEvents { - /** - * Raised when the rental process is fully finalized - */ + /** Emitted when the rental process is fully finalized */ finalized: () => void; + + /** Emitted when ExeUnit is successfully created and initialised */ + exeUnitCreated: (activity: Activity) => void; + + /** Emitted when the ExeUnit is successfully destroyed */ + exeUnitDestroyed: (activity: Activity) => void; + + /** Emitted when there is an error while creating or destroying the ExeUnit */ + error: (error: Error) => void; } export interface ResourceRentalOptions { @@ -143,11 +150,17 @@ export class ResourceRental { * the provider will terminate the Agreement and ResourceRental will be unuseble */ async destroyExeUnit() { - if (this.currentExeUnit !== null) { - await this.activityModule.destroyActivity(this.currentExeUnit.activity); - this.currentExeUnit = null; - } else { - throw new GolemUserError(`There is no exe-unit to destroy.`); + try { + if (this.currentExeUnit !== null) { + await this.activityModule.destroyActivity(this.currentExeUnit.activity); + this.currentExeUnit = null; + } else { + throw new GolemUserError(`There is no exe-unit to destroy.`); + } + } catch (error) { + this.events.emit("error", error); + this.logger.error(`Failed to destroy exe-unit. ${error}`, { activityId: this.currentExeUnit?.activity }); + throw error; } } @@ -166,9 +179,11 @@ export class ResourceRental { signalOrTimeout: abortSignal, ...this.resourceRentalOptions?.exeUnit, }); + this.events.emit("exeUnitCreated", activity); return this.currentExeUnit; })() .catch((error) => { + this.events.emit("error", error); this.logger.error(`Failed to create exe-unit. ${error}`, { agreementId: this.agreement.id }); throw error; })