Skip to content

Commit

Permalink
Merge pull request #102 from jjikky/feat/generate-test-data
Browse files Browse the repository at this point in the history
Feat/generate test data
  • Loading branch information
jjikky authored Nov 10, 2024
2 parents 2c25060 + f0611d3 commit 95a4318
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 15 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,6 @@ dist
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.pnp.*

scripts/data/*
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"prettier": "prettier --write --config ./.prettierrc './src/**'"
"prettier": "prettier --write --config ./.prettierrc './src/**'",
"generate:user": "node ./scripts/generate-users-data.js",
"generate:word": "node ./scripts/generate-words-data.js"
},
"author": "",
"license": "ISC",
Expand Down
50 changes: 50 additions & 0 deletions scripts/generate-users-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const fs = require('fs');

function generateRandomId() {
return Array(24)
.fill(0)
.map(() => Math.floor(Math.random() * 16).toString(16))
.join('');
}

function generateRandomNickname(index) {
return `user${index}`;
}

function generateUser(index) {
const now = new Date().toISOString();
return {
_id: { $oid: generateRandomId() },
deletedAt: null,
nickname: generateRandomNickname(index),
email: `user${index}@example.com`,
password: '$2b$10$NWhqlRrE5W0YMHlnaBi.CODbFjPZzvgT5G993eKoziVzrhH3M6KNC',
role: 'user',
snsId: null,
provider: null,
recentSearches: [],
requests: [],
createdAt: { $date: now },
updatedAt: { $date: now },
__v: 0,
};
}

function generateUsers(count) {
const users = [];
for (let i = 0; i < count; i++) {
users.push(generateUser(i));
}
return users;
}

async function generateAndSaveData(totalCount) {
const userData = generateUsers(totalCount);
const fileName = './scripts/data/test-users-data.json';
fs.writeFileSync(fileName, JSON.stringify(userData, null, 2));

console.log('✅ 10000개의 유저 데이터가 생성되었습니다.');
console.log('📁 파일 위치: users.json');
}

generateAndSaveData(10000).catch(console.error);
58 changes: 58 additions & 0 deletions scripts/generate-words-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const fs = require('fs');

const prefixes = ['A', 'Ab', 'Ac', 'Ad', 'Af', 'Ag', 'Al', 'Am', 'An', 'Ap', 'Ar', 'As', 'At', 'Au'];
const middles = ['sync', 'pi', 'data', 'net', 'web', 'cloud', 'tech', 'dev', 'sys', 'log'];
const suffixes = ['Service', 'API', 'Hub', 'Lab', 'Flow', 'Base', 'Core', 'Plus', 'Pro', 'Box'];

function generateRandomWord(index) {
const prefix = prefixes[Math.floor(Math.random() * prefixes.length)];
const middle = middles[Math.floor(Math.random() * middles.length)];
const suffix = suffixes[Math.floor(Math.random() * suffixes.length)];
return `${prefix}${middle}${suffix}${index}`;
}

function* generateWordBatch(totalCount, batchSize = 1000) {
for (let i = 0; i < totalCount; i += batchSize) {
const batch = [];
const currentBatchSize = Math.min(batchSize, totalCount - i);

for (let j = 0; j < currentBatchSize; j++) {
const word = generateRandomWord(i + j);
batch.push({
word,
awkPron: `어색한_${word}`,
comPron: `일반적인_${word}`,
info: `${word}에 대한 설명입니다. (테스트 데이터 ${i + j + 1})`,
suggestedBy: 'admin',
freq: Math.floor(Math.random() * 100),
});
}
yield batch;
}
}

async function generateAndSaveData(totalCount) {
console.time('Data Generation');
const fileName = './scripts/data/test-words-data.json';
const batchSize = 1000;
let currentBatch = 1;
const totalBatches = Math.ceil(totalCount / batchSize);

fs.writeFileSync(fileName, '[\n', 'utf8');

for (const batch of generateWordBatch(totalCount, batchSize)) {
console.log(`처리 중: ${currentBatch}/${totalBatches} 배치`);

const batchData = batch.map((item) => JSON.stringify(item)).join(',\n');
fs.appendFileSync(fileName, currentBatch === 1 ? batchData : ',\n' + batchData, 'utf8');

currentBatch++;
}

fs.appendFileSync(fileName, '\n]', 'utf8');

console.log(`✅ ${totalCount}개의 테스트 데이터 생성 완료!`);
console.log(`📁 파일 위치: ${fileName}`);
}

generateAndSaveData(100000).catch(console.error);
26 changes: 13 additions & 13 deletions src/routes/word/word.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const redisClient = require('../../common/modules/redis');

const wordSchema = new mongoose.Schema(
{
word: { type: String, required: true, unique: true },
word: { type: String, required: true },
awkPron: { type: String },
comPron: { type: String, required: true },
info: { type: String },
Expand All @@ -13,18 +13,7 @@ const wordSchema = new mongoose.Schema(
{ timestamps: true }
);

wordSchema.index({ word: 1 });

wordSchema.post(/^findOne/, async function (doc) {
const word = typeof this.getQuery().word === 'string' ? this.getQuery().word : doc?.word;
if (!word) {
console.error('❌ Error: No valid word found for Redis update');
return;
}

await redisClient.sendCommand(['ZINCRBY', 'popular_words', '1', word]);
await redisClient.expire('popular_words', 7200);
});
wordSchema.index({ word: 1 }, { unique: true });

wordSchema.pre(/^find|update|save|remove|delete|count/, function (next) {
this._startTime = Date.now();
Expand All @@ -33,8 +22,19 @@ wordSchema.pre(/^find|update|save|remove|delete|count/, function (next) {

wordSchema.post(/^find|update|save|remove|delete|count/, function (result, next) {
const latency = Date.now() - this._startTime;
console.log(this.getQuery());
console.log(`[${this.mongooseCollection.modelName}] ${this.op} query - ${latency}ms`);
next();
});

wordSchema.post(/^findOne/, async function (doc) {
const word = typeof this.getQuery().word === 'string' ? this.getQuery().word : doc?.word;
if (!word) {
console.error('❌ Error: No valid word found for Redis update');
return;
}
await redisClient.sendCommand(['ZINCRBY', 'popular_words', '1', word]);
await redisClient.expire('popular_words', 7200);
});

module.exports = mongoose.model('Word', wordSchema);

0 comments on commit 95a4318

Please sign in to comment.