From 18cd6be266a9ff63eaae3e149599f9f544ca0ad5 Mon Sep 17 00:00:00 2001 From: Dulana Peiris <57042272+du1ana@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:42:04 +0530 Subject: [PATCH] Modified lease destroy and recreate logic (#387) --- evernode-bootstrap-contract | 2 +- evernode-reputation-contract | 1 - installer/jshelper/index.js | 4 +- mb-xrpl/lib/message-board.js | 71 ++++++++++++++++++++++++++---------- reputationd | 2 +- 5 files changed, 56 insertions(+), 24 deletions(-) delete mode 160000 evernode-reputation-contract diff --git a/evernode-bootstrap-contract b/evernode-bootstrap-contract index b532568..13b6f70 160000 --- a/evernode-bootstrap-contract +++ b/evernode-bootstrap-contract @@ -1 +1 @@ -Subproject commit b5325680455943694ee0d804092386b7b268687b +Subproject commit 13b6f708bf86af5a8518d27f7573291a5fdeeaab diff --git a/evernode-reputation-contract b/evernode-reputation-contract deleted file mode 160000 index c69fb62..0000000 --- a/evernode-reputation-contract +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c69fb62cbe26ab7c76b5e7ceccda74dede85816c diff --git a/installer/jshelper/index.js b/installer/jshelper/index.js index d2c19c4..0dfecf6 100644 --- a/installer/jshelper/index.js +++ b/installer/jshelper/index.js @@ -627,8 +627,8 @@ const funcs = { catch (err) { await xrplApi.disconnect(); if (err.data?.error === 'actNotFound') { - const governorClient = await evernode.HookClientFactory.create(evernode.HookTypes.governor); - await governorClient.connect(); + const governorClient = await evernode.HookClientFactory.create(evernode.HookTypes.governor, { config: hostClient.config }); + await governorClient.connect({ skipConfigs: true }); return { success: true, result: `${governorClient.config.hostRegFee}` }; } return { success: false, result: "Error occurred in websocket connection." }; diff --git a/mb-xrpl/lib/message-board.js b/mb-xrpl/lib/message-board.js index a490754..5c14cb2 100644 --- a/mb-xrpl/lib/message-board.js +++ b/mb-xrpl/lib/message-board.js @@ -11,7 +11,8 @@ const LeaseStatus = { ACQUIRING: 'Acquiring', ACQUIRED: 'Acquired', FAILED: 'Failed', - EXPIRED: 'Expired', + DESTROYED: 'Destroyed', + BURNED: 'Burned', SASHI_TIMEOUT: 'SashiTimeout', EXTENDED: 'Extended' } @@ -250,6 +251,14 @@ class MessageBoard { } }); + //Initially prune orphan instances + console.log(`Starting the initial prune job...`); + await this.#acquireLeaseUpdateLock(); + await this.#pruneOrphanLeases().catch(console.error).finally(async () => { + await this.#releaseLeaseUpdateLock(); + }); + console.log(`Ended the initial prune job.`); + // Start a job to expire instances and check for halts this.#startSashimonoClockScheduler(); @@ -511,8 +520,6 @@ class MessageBoard { */ // await this.updateLeaseStatus(x.txHash, LeaseStatus.EXPIRED); - // Delete the lease record related to this instance (Permanent Delete). - await this.deleteLeaseRecord(lease.txHash); // Remove from the queue this.#instanceExpirationQueue = this.#instanceExpirationQueue.filter(i => i.containerName != lease.containerName); @@ -530,8 +537,9 @@ class MessageBoard { } // Update the registry with the active instance count. await this.hostClient.updateRegInfo(this.activeInstanceCount, null, null, null, null, null, null, null, null, null, null, { submissionRef: submissionRefs?.refs[0] }); - console.log(`Destroyed ${lease.containerName}`); + console.log(`${lease.containerName} queued for expiry.`) }); + } catch (e) { console.error(e); @@ -583,7 +591,7 @@ class MessageBoard { await this.#pruneOrphanLeases().catch(console.error).finally(async () => { await this.#releaseLeaseUpdateLock(); }); - console.log(`Stopped the scheduled prune job.`); + console.log(`Ended the scheduled prune job.`); setTimeout(async () => { await scheduler(); }, timeout); @@ -681,7 +689,7 @@ class MessageBoard { const instances = (await this.sashiDb.getValues(this.sashiTable)); this.sashiDb.close(); this.db.open(); - const leases = (await this.db.getValues(this.leaseTable)); + const leases = (await this.getLeaseRecords()); this.db.close(); let activeInstanceCount = leases.filter(r => (r.status === LeaseStatus.ACQUIRED || r.status === LeaseStatus.EXTENDED)).length; @@ -703,12 +711,15 @@ class MessageBoard { if (lease.status === LeaseStatus.ACQUIRING || !uriToken) { console.log(`Pruning orphan instance ${instance.name}...`); await this.sashiCli.destroyInstance(instance.name); + this.db.open(); + let leaseTxHash = await this.getLeaseTxHash(instance.name); + await this.updateLeaseStatus(leaseTxHash, LeaseStatus.DESTROYED); + this.db.close(); // After destroying, If the URIToken is owned by the tenant, burn the URIToken and recreate and refund the tenant. if (uriToken) { const uriInfo = evernode.UtilHelpers.decodeLeaseTokenUri(uriToken.URI); await this.recreateLeaseOffer(instance.name, uriInfo.leaseIndex, uriInfo.outboundIP?.address); - await this.#queueAction(async (submissionRefs) => { submissionRefs.refs ??= [{}]; // Check again wether the transaction is validated before retry. @@ -723,16 +734,16 @@ class MessageBoard { console.log(`Refunding tenant ${lease.tenant_xrp_address}...`); await this.hostClient.refundTenant(lease.tx_hash, lease.tenant_xrp_address, uriInfo.leaseAmount.toString(), { submissionRef: submissionRefs?.refs[0] }); }); - } + } else { + // Remove the lease record. + if (lease) { + this.db.open(); + await this.deleteLeaseRecord(lease.tx_hash); + this.db.close(); - // Remove the lease record. - if (lease) { - this.db.open(); - await this.deleteLeaseRecord(lease.tx_hash); - this.db.close(); - - if (lease.status === LeaseStatus.ACQUIRED || lease.status === LeaseStatus.EXTENDED) - activeInstanceCount--; + if (lease.status === LeaseStatus.ACQUIRED || lease.status === LeaseStatus.EXTENDED) + activeInstanceCount--; + } } } } @@ -971,10 +982,15 @@ class MessageBoard { retry = false; } } - if (retry) { + + this.db.open(); + let leaseTxHash = await this.getLeaseTxHash(uriTokenId); + if (retry && await this.getLeaseStatus(leaseTxHash) == LeaseStatus.DESTROYED) { // Burn the URIToken and recreate the offer. await this.hostClient.expireLease(uriTokenId, { submissionRef: submissionRefs?.refs[0] }).catch(console.error); + await this.updateLeaseStatus(leaseTxHash, LeaseStatus.BURNED); } + this.db.close(); // We refresh the config here, So if the purchaserTargetPrice is updated by the purchaser service, the new value will be taken. await this.hostClient.refreshConfig(); @@ -989,10 +1005,15 @@ class MessageBoard { retry = false; } } - if (retry) { + this.db.open(); + if (retry && await this.getLeaseStatus(leaseTxHash) == LeaseStatus.BURNED) { const leaseAmount = this.cfg.xrpl.leaseAmount ? this.cfg.xrpl.leaseAmount : parseFloat(this.hostClient.config.purchaserTargetPrice); await this.hostClient.offerLease(leaseIndex, leaseAmount, appenv.TOS_HASH, outboundIP, { submissionRef: submissionRefs?.refs[1] }).catch(console.error); + //Delete the lease record related to this instance (Permanent Delete). + await this.deleteLeaseRecord(leaseTxHash); + console.log(`Destroyed ${uriTokenId}.`); } + this.db.close(); }); } @@ -1054,7 +1075,7 @@ class MessageBoard { if (diff > threshold) { console.error(`Sashimono busy timeout. Took: ${diff} seconds. Threshold: ${threshold} seconds`); // Update the lease status of the request to 'SashiTimeout'. - await this.updateAcquireStatus(acquireRefId, LeaseStatus.SASHI_TIMEOUT); + await this.updateLeaseStatus(acquireRefId, LeaseStatus.SASHI_TIMEOUT); await this.recreateLeaseOffer(uriTokenId, leaseIndex, uriInfo?.outboundIP?.address); } else { @@ -1166,6 +1187,8 @@ class MessageBoard { async destroyInstance(containerName, leaseIndex, outboundIP = null) { // Destroy the instance. await this.sashiCli.destroyInstance(containerName); + let leaseTxHash = await this.getLeaseTxHash(containerName); + await this.updateLeaseStatus(leaseTxHash, LeaseStatus.DESTROYED); await this.recreateLeaseOffer(containerName, leaseIndex, outboundIP).catch(console.error); } @@ -1348,6 +1371,16 @@ class MessageBoard { await this.db.updateValue(this.leaseTable, { status: status }, { tx_hash: txHash }); } + async getLeaseStatus(tx_hash) { + const leaseData = await this.db.getValues(this.leaseTable, { tx_hash: tx_hash }); + return leaseData[0]?.status; + } + + async getLeaseTxHash(container_name) { + const leaseData = await this.db.getValues(this.leaseTable, { container_name: container_name }); + return leaseData[0]?.tx_hash; + } + /** * Sample savingData * Note : The keys of the object should match with the sqlite db column names diff --git a/reputationd b/reputationd index 08068e9..399e2f5 160000 --- a/reputationd +++ b/reputationd @@ -1 +1 @@ -Subproject commit 08068e9909efb0db9cdc64c64cfc93d312a689e7 +Subproject commit 399e2f5d275f8af20f5f2be05e17987f9093e788