github : https://github.com/codestates/BEB_01_WhyDoesItWork/tree/hojin
- 들어가지지 않는다면 아직 프로젝트 기간이 끝나지 않았다는 것을 의미합니다!
제가 고민했던 문제는 매우 간단하지만 저에게는 처음겪어보는 문제였습니다.
쉽게 말해 데이터를 가져오고 저장하는 시간에 대한 내용입니다.
가나슈 네트워크를 통해 테스트해본결과 코드가 정상적으로 작동이 되었지만 infura.io
를 통해 롭스텐 네트워크와 소통할떄에는 오류가 발생을 하였습니다.
infura.io
를 통해서 노드와 네트워크를 연결하게 되면 해당 노드의 네트워크 환경에 따라서 블록 데이터를 가져오는 시간이 다르게 됩니다.
그러기 떄문에 저희는 데이터를 일단 서버의 DB에 저장을 해두고
발생하는 트랜잭션을 담을 또다른 DB가 필요합니다.
일단 특정 행동을 통해서 DB에 저장하고 DB를 활용함으로써 값을 update해주고 트랜잭션을 저장해 두었다가 이후 한번에 전송을 함으로써 서버의 과부화를 방지할수 있습니다.
저는 배치서버를 구축해본 적이 없고 단순히 pm2가 무엇인지에 대해서만 학습을 하였습니다.
일단 pm2를 활용하는데에 자신이 없기 떄문에 코드스테이츠에서 제공하는 배치서버의 코드를 보며 이해를 해 보았습니다.
const getLastestTransactions = async () => {
try {
// 최신 블록번호가 마지막에 확인한 블록번호보다 크다면,
// 그 차이만큼 블록을 조회하기 위해 범위 업데이트
await web3.eth.getBlockNumber((err, result) => {
if (err) throw err;
if (result > lastest) {
lastest = result;
}
});
if (checkedBlockNum === lastest) {
// 만약 최신 블럭과 같다면 빈 배열을 리턴
return [];
} else {
// 최신 블록과 차이가 있다면 그 차이만큼 for문을 돌려서 조회
for (let i = checkedBlockNum + 1; i <= lastest; i++) {
const block = await web3.eth.getBlock(i);
// 트랜잭션 해시로 모든 트랜잭션 조회
for (let tx of block.transactions) {
// 트랜잭션을 조회하고 해당 값을 allTransactions에 push
allTransactions.push(getTx(tx));
}
}
// 모든 트랜잭션 중에서, 조건에 부합하는 트랜잭션을 배열로 리턴(Promise)
// Promise.all은 인자로 받은 값들을 모두 처리한뒤에 결과값을 return
return Promise.all(allTransactions)
.then((data) => {
const result = [];
for (let tx of data) {
if (tx.from === contractAddress || tx.to === contractAddress) {
result.push(tx);
}
}
return result;
})
.then((data) => {
// 가장 마지막에 확인한 블록번호 저장
fs.writeFileSync(
path.join(basePath, "/utils/blockNumber"),
String(lastest)
);
return data;
});
}
} catch (err) {
console.log(err);
}
};
주석을 통해서 개인적으로 정리를 해보앗습니다.
생각보다 로직 자체는 매우 간단하였습니다.
간단하게 최신 블록을 조회하고 해당 블록이 내가 알고 잇는 블럭과 다르면 업데이트 해주고 공백에 대한 값을 배열에 넣어주고 조회를 합니다.
이떄 계정의 주소값이 같은 값들만 처리를 해주며 비동기적 처리를 하기 위해 Promise.all
을 사용하여 반환해 줍니다.
const storeData = async (data) => await Transactions.create(data);
const startTask = async () => {
let arr = [];
getLastestTransactions().then((result) => {
for (let data of result) {
arr.push(storeData(data));
}
if (arr.length > 0) {
Promise.all(arr)
.then(async () => {
console.log("Done.");
await sequelize.close();
})
.then(() => {
arr = [];
})
.catch(async (err) => {
console.log(err);
await sequelize.close();
});
} else {
console.log("No transactions");
}
});
};
이후 함수를 실행해 줌으로써 해당 값에 데이터가 들어있다면 DB를 업데이트 해주고 종료하게 됩니다.
이러한 부분을 토대로 제 나름대로 배치서버를 구현할수 있으면 구현을 해보고자 하며 최대한 진행을 해보고자 합니다.
일단 기본적인 DB설정은 끝났습니다.
가나슈를 통한 네트워크 연결을 하면 web3코드를 진행하는데에 있어서 별다른 문제점이 없기 떄문에 web3코드를 작성하기 보다는 배치서버를 구현하는데에 좀더 집중을 해보고자 합니다.
웹사이트의 구동 DB는 mongoose를 사용하고 있지만
mysql에서도 어느정도 익숙해 지는 것이 좋다고 생각을 하기 떄문에 배치서버는 mysql로 구현을 해보고자 합니다!!