Skip to content

Commit

Permalink
update to inmemory queue
Browse files Browse the repository at this point in the history
  • Loading branch information
okedeji committed Jul 20, 2024
1 parent 147e6e0 commit 18cbec5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 41 deletions.
17 changes: 17 additions & 0 deletions checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,21 @@ export class FrequencyChecker {
const request = await db.get(requestId);
return request
}

async put(key, value) {
await this.db.put(key, value)
}

async get (address) {
try {
const status = await this.db.get(address);
return status
} catch (err) {
if (err.notFound) {
console.log('Address not found')
} else {
console.log('Database error')
}
}
}
}
101 changes: 62 additions & 39 deletions faucet.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,9 @@ import { bech32 } from 'bech32';
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { SigningStargateClient } from "@cosmjs/stargate";

import { Mutex } from 'async-mutex';
import { v4 } from 'uuid';

import conf from './config/config.js'
import { FrequencyChecker } from './checker.js';

const mutex = new Mutex();

// load config
console.log("loaded config: ", conf)

Expand Down Expand Up @@ -54,6 +49,43 @@ app.get('/config.json', async (req, res) => {
res.send(project);
})

const queue = [];
const addressStatus = {};

// Enqueue address
const enqueueAddress = async (statusAddress) => {
console.log('Enqueueing address:', statusAddress);
if (!addressStatus[statusAddress] || addressStatus[statusAddress] === 'cleared') {
if (!queue.includes(statusAddress)) {
queue.push(statusAddress);
}
}
};

// Process addresses
const processAddresses = async (chain) => {
console.log('Starting to process addresses');
while (true) {
console.log(`the lenght of the queue: ${queue.length}`);
if (queue.length > 0) {
const statusAddress = queue.shift();
const address = statusAddress.replace('status:', '');
try {
await sendTx(address, chain);
} catch (error) {
console.log(error, 'error')
}
addressStatus[statusAddress] = 'Completed';
await checker.put(statusAddress, 'Completed');
}

console.log('Waiting for 5 seconds cooldown period');
await new Promise(resolve => setTimeout(resolve, 5000));
}
};

processAddresses(conf.blockchains[0].name);

app.get('/balance/:chain', async (req, res) => {
const { chain }= req.params

Expand Down Expand Up @@ -88,23 +120,26 @@ app.get('/balance/:chain', async (req, res) => {
res.send(balance);
})

app.get('/status/:requestId', async (req, res, next) => {
app.get('/status/:address', async (req, res, next) => {
return Promise.resolve().then(async () => {
const { requestId } = req.params;
const { address } = req.params;
const statusAddress = `status:${address}`;

const status = await checker.getRequestStatus(requestId);
if (status.statuses.length > 0) {
res.json(status);
} else {
res.status(404).json({ error: 'Request ID not found' });
let status = await checker.get(statusAddress);
if (!status) {
status = 'not found';
}
res.json({ code: 0, status });

if (status != 'not found') {
addressStatus[statusAddress] = 'cleared';
await checker.put(statusAddress, 'cleared');
}
}).catch(next)
});

app.get('/send/:chain/:address', async (req, res, next) => {
return Promise.resolve().then(async () => {
const requestId = v4();
await checker.updateRequestStatus(requestId, 'pending', 'Request received');

const {chain, address} = req.params;
const ip = req.headers['x-real-ip'] || req.headers['X-Real-IP'] || req.headers['X-Forwarded-For'] || req.ip
Expand All @@ -114,35 +149,24 @@ app.get('/send/:chain/:address', async (req, res, next) => {
const chainConf = conf.blockchains.find(x => x.name === chain)
if (chainConf && (address.startsWith(chainConf.sender.option.prefix) || address.startsWith('0x'))) {
if( await checker.checkAddress(address, chain) && await checker.checkIp(`${chain}${ip}`, chain) ) {

res.send({ requestId, message: "Faucet processing request", recipient: address})
checker.update(`${chain}${ip}`) // get ::1 on localhost

const release = await mutex.acquire();
let sendRes;
try {
const sendRes = await sendTx(address, chain);
await checker.updateRequestStatus(requestId, 'success', 'request processed successfully', sendRes);
await checker.update(address)
} catch (err) {
console.log(err, 'error');
await checker.updateRequestStatus(requestId, 'failed', 'Failed, Please contact to admin.');
} finally {
release();
const statusAddress = `status:${address}`
if (addressStatus[statusAddress] === 'Completed') {
console.log('Address has already received faucet');
return res.status(400).json({ code: 1, message: 'Address has already received faucet' });
}

await enqueueAddress(statusAddress);
res.json({ code: 0, message: 'Address enqueued for faucet processing. Please check status with your address' });

await checker.update(address)

}else {
await checker.updateRequestStatus(requestId, 'failed', `Too Many Requests`);
res.send({
result: {
requestId,
message: 'Too Many Requests',
recipient: address
}
})
res.send({ code: 1, message: 'Too Many Requests'})
}
} else {
await checker.updateRequestStatus(requestId, 'failed', `Address [${address}] is not supported.`);
res.send({requestId, message: `Address [${address}] is not supported.`, recipient: address })
res.send({ code: 1, message: `Address [${address}] is not supported.`, recipient: address })
}
// } catch (err) {
// console.error(err);
Expand All @@ -151,8 +175,7 @@ app.get('/send/:chain/:address', async (req, res, next) => {

} else {
// send result
await checker.updateRequestStatus(requestId, 'failed', `address not provided`);
res.send({requestId, message: 'address is required' });
res.send({ code: 0, message: 'address is required' });
}}).catch(next)
})

Expand Down
4 changes: 2 additions & 2 deletions views/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@
document.getElementById("address-button-loading").style.display = 'none';
// show result
this.message = `
<div class="alert alert-success alert-dismissible show fade mt-2" role="alert">
<li>${data.message} with ID: ${data.requestId}</li>
<div class="alert alert-${data.code === 0 ? 'success' : 'danger'} alert-dismissible show fade mt-2" role="alert">
<li>${data.message}</li>
</div>
`;
} catch (e) {
Expand Down

0 comments on commit 18cbec5

Please sign in to comment.