Modified lease destroy and recreate logic (#387)

This commit is contained in:
Dulana Peiris
2024-06-14 11:42:04 +05:30
committed by GitHub
parent 4f63098d88
commit 18cd6be266
5 changed files with 56 additions and 24 deletions

Submodule evernode-reputation-contract deleted from c69fb62cbe

View File

@@ -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." };

View File

@@ -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