diff --git a/.env.example b/.env.example index 769e0fa8..ea107da9 100644 --- a/.env.example +++ b/.env.example @@ -16,3 +16,10 @@ CORS_WHITELIST=[CORS 정책에서 허용하는 도메인의 목록(e.g. ["http:/ GOOGLE_APPLICATION_CREDENTIALS=[GOOGLE_APPLICATION_CREDENTIALS JSON] TEST_ACCOUNTS=[스팍스SSO로 로그인시 무조건 테스트로 로그인이 가능한 허용 아이디 목록] SLACK_REPORT_WEBHOOK_URL=[Slack 웹훅 URL들이 담긴 JSON] + +# optional environment variables for taxiSampleGenerator +SAMPLE_NUM_OF_ROOMS=[방의 개수] +SAMPLE_NUM_OF_CHATS=[각 방의 채팅 개수] +SAMPLE_MAXIMUM_INTERVAL_BETWEEN_CHATS=[채팅 간 최대 시간 간격(단위: 초, 실수도 가능)] +SAMPLE_OCCURENCE_OF_JOIN=[새로운 채팅이 입장 메세지일 확률(0 ~ 1 사이의 값)] +SAMPLE_OCCURENCE_OF_ABORT=[새로운 채팅이 퇴장 메세지일 확률(0 ~ 1 사이의 값)] \ No newline at end of file diff --git a/.github/workflows/test_ci.yml b/.github/workflows/test_ci.yml index 29f7f21b..2ccc5415 100644 --- a/.github/workflows/test_ci.yml +++ b/.github/workflows/test_ci.yml @@ -29,20 +29,6 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: 'pnpm' - - id: submodule-local - name: Save local version of submodule - run: echo "ver=`cd sampleGenerator && git log --pretty="%h" -1 && cd ..`" >> $GITHUB_OUTPUT - - id: submodule-origin - name: Save origin version of submodule - run: echo "ver=`cd sampleGenerator && git log origin --pretty="%h" -1 && cd ..`" >> $GITHUB_OUTPUT - - name: Check submodule version - if: ${{ steps.submodule-local.outputs.ver != steps.submodule-origin.outputs.ver }} - uses: actions/github-script@v3 - with: - script: | - core.setFailed('Please update submodule to the latest version by using \"git submodule update --remote\"') - - name: Install sampleGenerator dependencies from package-lock.json - run: cd sampleGenerator && pnpm i --force --frozen-lockfile && cd .. - name: Install taxi-back dependencies from package-lock.json run: pnpm i --force --frozen-lockfile - name: Run unit tests diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index f15db4d8..00000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "sampleGenerator"] - path = sampleGenerator - url = https://github.com/sparcs-kaist/taxiSampleGenerator - branch = main diff --git a/README.md b/README.md index 26cda418..9a335131 100644 --- a/README.md +++ b/README.md @@ -49,4 +49,3 @@ See [contributors](https://github.com/sparcs-kaist/taxi-front/graphs/contributor - app : https://github.com/sparcs-kaist/taxi-app - docker : https://github.com/sparcs-kaist/taxi-docker - figma : https://www.figma.com/file/li34hP1oStJAzLNjcG5KjN/SPARCS-Taxi?node-id=0%3A1 - - taxiSampleGenerator : https://github.com/sparcs-kaist/taxiSampleGenerator diff --git a/app.js b/app.js index f8c24842..a26c4b46 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,12 @@ // 모듈 require const express = require("express"); const http = require("http"); -const { nodeEnv, port: httpPort, eventConfig } = require("./loadenv"); +const { + nodeEnv, + port: httpPort, + eventConfig, + mongo: mongoUrl, +} = require("./loadenv"); const logger = require("./src/modules/logger"); const { connectDatabase } = require("./src/modules/stores/mongo"); const { startSocketServer } = require("./src/modules/socket"); @@ -13,7 +18,7 @@ require("./src/modules/fcm").initializeApp(); const app = express(); // 데이터베이스 연결 -connectDatabase(); +connectDatabase(mongoUrl); // [Middleware] request body 파싱 app.use(express.urlencoded({ extended: false })); diff --git a/loadenv.js b/loadenv.js index f7224601..789e21db 100644 --- a/loadenv.js +++ b/loadenv.js @@ -43,5 +43,5 @@ module.exports = { slackWebhookUrl: { report: process.env.SLACK_REPORT_WEBHOOK_URL || "", // optional }, - eventConfig: process.env.EVENT_CONFIG && JSON.parse(process.env.EVENT_CONFIG), + eventConfig: process.env.EVENT_CONFIG && JSON.parse(process.env.EVENT_CONFIG), // optional }; diff --git a/package.json b/package.json index 307baba9..7c0c7248 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "serve": "cross-env TZ='Asia/Seoul' NODE_ENV=production node app.js", "runscript": "cross-env TZ='Asia/Seoul' NODE_ENV=production node", "lint": "npx eslint --fix .", - "sample": "cd sampleGenerator && npm start && cd .." + "sample": "cd src/sampleGenerator && npm start && cd .." }, "engines": { "node": ">=18.0.0", @@ -60,7 +60,7 @@ "eslint": "^8.22.0", "eslint-plugin-mocha": "^10.1.0", "mocha": "^10.2.0", - "mongodb": "^6.2.0", + "mongodb": "^4.1.0", "nodemon": "^3.0.1", "supertest": "^6.2.4" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 545f1c18..d7206c1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,7 +34,7 @@ dependencies: version: 2.2.0 connect-mongo: specifier: ^4.6.0 - version: 4.6.0(express-session@1.17.3)(mongodb@6.2.0) + version: 4.6.0(express-session@1.17.3)(mongodb@4.17.1) connect-redis: specifier: ^6.1.3 version: 6.1.3 @@ -122,8 +122,8 @@ devDependencies: specifier: ^10.2.0 version: 10.2.0 mongodb: - specifier: ^6.2.0 - version: 6.2.0 + specifier: ^4.1.0 + version: 4.17.1 nodemon: specifier: ^3.0.1 version: 3.0.1 @@ -228,7 +228,6 @@ packages: '@aws-crypto/util': 3.0.0 '@aws-sdk/types': 3.425.0 tslib: 1.14.1 - dev: false optional: true /@aws-crypto/ie11-detection@3.0.0: @@ -236,7 +235,6 @@ packages: requiresBuild: true dependencies: tslib: 1.14.1 - dev: false optional: true /@aws-crypto/sha256-browser@3.0.0: @@ -251,7 +249,6 @@ packages: '@aws-sdk/util-locate-window': 3.310.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 - dev: false optional: true /@aws-crypto/sha256-js@3.0.0: @@ -261,7 +258,6 @@ packages: '@aws-crypto/util': 3.0.0 '@aws-sdk/types': 3.425.0 tslib: 1.14.1 - dev: false optional: true /@aws-crypto/supports-web-crypto@3.0.0: @@ -269,7 +265,6 @@ packages: requiresBuild: true dependencies: tslib: 1.14.1 - dev: false optional: true /@aws-crypto/util@3.0.0: @@ -279,7 +274,6 @@ packages: '@aws-sdk/types': 3.425.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 - dev: false optional: true /@aws-sdk/client-cognito-identity@3.427.0: @@ -326,7 +320,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/client-sso@3.427.0: @@ -370,7 +363,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/client-sts@3.427.0: @@ -418,7 +410,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/credential-provider-cognito-identity@3.427.0: @@ -433,7 +424,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/credential-provider-env@3.425.0: @@ -445,7 +435,6 @@ packages: '@smithy/property-provider': 2.0.12 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/credential-provider-http@3.425.0: @@ -460,7 +449,6 @@ packages: '@smithy/protocol-http': 3.0.7 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/credential-provider-ini@3.427.0: @@ -480,7 +468,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/credential-provider-node@3.427.0: @@ -501,7 +488,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/credential-provider-process@3.425.0: @@ -514,7 +500,6 @@ packages: '@smithy/shared-ini-file-loader': 2.2.0 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/credential-provider-sso@3.427.0: @@ -531,7 +516,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/credential-provider-web-identity@3.425.0: @@ -543,7 +527,6 @@ packages: '@smithy/property-provider': 2.0.12 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/credential-providers@3.427.0: @@ -569,7 +552,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/middleware-host-header@3.425.0: @@ -581,7 +563,6 @@ packages: '@smithy/protocol-http': 3.0.7 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/middleware-logger@3.425.0: @@ -592,7 +573,6 @@ packages: '@aws-sdk/types': 3.425.0 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/middleware-recursion-detection@3.425.0: @@ -604,7 +584,6 @@ packages: '@smithy/protocol-http': 3.0.7 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/middleware-sdk-sts@3.425.0: @@ -616,7 +595,6 @@ packages: '@aws-sdk/types': 3.425.0 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/middleware-signing@3.425.0: @@ -631,7 +609,6 @@ packages: '@smithy/types': 2.3.5 '@smithy/util-middleware': 2.0.4 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/middleware-user-agent@3.427.0: @@ -644,7 +621,6 @@ packages: '@smithy/protocol-http': 3.0.7 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/region-config-resolver@3.425.0: @@ -657,7 +633,6 @@ packages: '@smithy/util-config-provider': 2.0.0 '@smithy/util-middleware': 2.0.4 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/token-providers@3.427.0: @@ -702,7 +677,6 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false optional: true /@aws-sdk/types@3.425.0: @@ -712,7 +686,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/util-endpoints@3.427.0: @@ -723,7 +696,6 @@ packages: '@aws-sdk/types': 3.425.0 '@smithy/node-config-provider': 2.1.1 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/util-locate-window@3.310.0: @@ -732,7 +704,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@aws-sdk/util-user-agent-browser@3.425.0: @@ -743,7 +714,6 @@ packages: '@smithy/types': 2.3.5 bowser: 2.11.0 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/util-user-agent-node@3.425.0: @@ -760,7 +730,6 @@ packages: '@smithy/node-config-provider': 2.1.1 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@aws-sdk/util-utf8-browser@3.259.0: @@ -768,7 +737,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@babel/code-frame@7.22.5: @@ -2276,7 +2244,7 @@ packages: resolution: {integrity: sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==} dependencies: '@firebase/util': 1.9.3 - tslib: 2.6.1 + tslib: 2.6.2 dev: false /@firebase/database-compat@0.3.4: @@ -2287,7 +2255,7 @@ packages: '@firebase/database-types': 0.10.4 '@firebase/logger': 0.4.0 '@firebase/util': 1.9.3 - tslib: 2.6.1 + tslib: 2.6.2 dev: false /@firebase/database-types@0.10.4: @@ -2305,19 +2273,19 @@ packages: '@firebase/logger': 0.4.0 '@firebase/util': 1.9.3 faye-websocket: 0.11.4 - tslib: 2.6.1 + tslib: 2.6.2 dev: false /@firebase/logger@0.4.0: resolution: {integrity: sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==} dependencies: - tslib: 2.6.1 + tslib: 2.6.2 dev: false /@firebase/util@1.9.3: resolution: {integrity: sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==} dependencies: - tslib: 2.6.1 + tslib: 2.6.2 dev: false /@floating-ui/core@1.4.1: @@ -2533,6 +2501,7 @@ packages: requiresBuild: true dependencies: sparse-bitfield: 3.0.3 + optional: true /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -2787,7 +2756,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/config-resolver@2.0.14: @@ -2800,7 +2768,6 @@ packages: '@smithy/util-config-provider': 2.0.0 '@smithy/util-middleware': 2.0.4 tslib: 2.6.2 - dev: false optional: true /@smithy/credential-provider-imds@2.0.16: @@ -2813,7 +2780,6 @@ packages: '@smithy/types': 2.3.5 '@smithy/url-parser': 2.0.11 tslib: 2.6.2 - dev: false optional: true /@smithy/eventstream-codec@2.0.11: @@ -2824,7 +2790,6 @@ packages: '@smithy/types': 2.3.5 '@smithy/util-hex-encoding': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/fetch-http-handler@2.2.2: @@ -2836,7 +2801,6 @@ packages: '@smithy/types': 2.3.5 '@smithy/util-base64': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/hash-node@2.0.11: @@ -2848,7 +2812,6 @@ packages: '@smithy/util-buffer-from': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/invalid-dependency@2.0.11: @@ -2857,7 +2820,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/is-array-buffer@2.0.0: @@ -2866,7 +2828,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@smithy/middleware-content-length@2.0.13: @@ -2877,7 +2838,6 @@ packages: '@smithy/protocol-http': 3.0.7 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/middleware-endpoint@2.0.11: @@ -2890,7 +2850,6 @@ packages: '@smithy/url-parser': 2.0.11 '@smithy/util-middleware': 2.0.4 tslib: 2.6.2 - dev: false optional: true /@smithy/middleware-retry@2.0.16: @@ -2906,7 +2865,6 @@ packages: '@smithy/util-retry': 2.0.4 tslib: 2.6.2 uuid: 8.3.2 - dev: false optional: true /@smithy/middleware-serde@2.0.11: @@ -2916,7 +2874,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/middleware-stack@2.0.5: @@ -2926,7 +2883,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/node-config-provider@2.1.1: @@ -2938,7 +2894,6 @@ packages: '@smithy/shared-ini-file-loader': 2.2.0 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/node-http-handler@2.1.7: @@ -2951,7 +2906,6 @@ packages: '@smithy/querystring-builder': 2.0.11 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/property-provider@2.0.12: @@ -2961,7 +2915,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/protocol-http@3.0.7: @@ -2971,7 +2924,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/querystring-builder@2.0.11: @@ -2982,7 +2934,6 @@ packages: '@smithy/types': 2.3.5 '@smithy/util-uri-escape': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/querystring-parser@2.0.11: @@ -2992,7 +2943,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/service-error-classification@2.0.4: @@ -3001,7 +2951,6 @@ packages: requiresBuild: true dependencies: '@smithy/types': 2.3.5 - dev: false optional: true /@smithy/shared-ini-file-loader@2.2.0: @@ -3011,7 +2960,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/signature-v4@2.0.11: @@ -3027,7 +2975,6 @@ packages: '@smithy/util-uri-escape': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/smithy-client@2.1.10: @@ -3039,7 +2986,6 @@ packages: '@smithy/types': 2.3.5 '@smithy/util-stream': 2.0.15 tslib: 2.6.2 - dev: false optional: true /@smithy/types@2.3.5: @@ -3048,7 +2994,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@smithy/url-parser@2.0.11: @@ -3058,7 +3003,6 @@ packages: '@smithy/querystring-parser': 2.0.11 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/util-base64@2.0.0: @@ -3068,7 +3012,6 @@ packages: dependencies: '@smithy/util-buffer-from': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/util-body-length-browser@2.0.0: @@ -3076,7 +3019,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@smithy/util-body-length-node@2.1.0: @@ -3085,7 +3027,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@smithy/util-buffer-from@2.0.0: @@ -3095,7 +3036,6 @@ packages: dependencies: '@smithy/is-array-buffer': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/util-config-provider@2.0.0: @@ -3104,7 +3044,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@smithy/util-defaults-mode-browser@2.0.14: @@ -3117,7 +3056,6 @@ packages: '@smithy/types': 2.3.5 bowser: 2.11.0 tslib: 2.6.2 - dev: false optional: true /@smithy/util-defaults-mode-node@2.0.18: @@ -3132,7 +3070,6 @@ packages: '@smithy/smithy-client': 2.1.10 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/util-hex-encoding@2.0.0: @@ -3141,7 +3078,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@smithy/util-middleware@2.0.4: @@ -3151,7 +3087,6 @@ packages: dependencies: '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/util-retry@2.0.4: @@ -3162,7 +3097,6 @@ packages: '@smithy/service-error-classification': 2.0.4 '@smithy/types': 2.3.5 tslib: 2.6.2 - dev: false optional: true /@smithy/util-stream@2.0.15: @@ -3178,7 +3112,6 @@ packages: '@smithy/util-hex-encoding': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@smithy/util-uri-escape@2.0.0: @@ -3187,7 +3120,6 @@ packages: requiresBuild: true dependencies: tslib: 2.6.2 - dev: false optional: true /@smithy/util-utf8@2.0.0: @@ -3197,7 +3129,6 @@ packages: dependencies: '@smithy/util-buffer-from': 2.0.0 tslib: 2.6.2 - dev: false optional: true /@socket.io/component-emitter@3.1.0: @@ -4211,7 +4142,6 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: false /base64id@2.0.0: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} @@ -4270,7 +4200,6 @@ packages: /bowser@2.11.0: resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} requiresBuild: true - dev: false optional: true /brace-expansion@1.1.11: @@ -4310,11 +4239,6 @@ packages: engines: {node: '>=6.9.0'} dependencies: buffer: 5.7.1 - dev: false - - /bson@6.2.0: - resolution: {integrity: sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==} - engines: {node: '>=16.20.1'} /buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -4337,7 +4261,6 @@ packages: dependencies: base64-js: 1.5.1 ieee754: 1.1.13 - dev: false /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} @@ -4570,7 +4493,7 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - /connect-mongo@4.6.0(express-session@1.17.3)(mongodb@6.2.0): + /connect-mongo@4.6.0(express-session@1.17.3)(mongodb@4.17.1): resolution: {integrity: sha512-8new4Z7NLP3CGP65Aw6ls3xDBeKVvHRSh39CXuDZTQsvpeeU9oNMzfFgvqmHqZ6gWpxIl663RyoVEmCAGf1yOg==} engines: {node: '>=10'} peerDependencies: @@ -4580,7 +4503,7 @@ packages: debug: 4.3.4 express-session: 1.17.3 kruptein: 3.0.6 - mongodb: 6.2.0 + mongodb: 4.17.1 transitivePeerDependencies: - supports-color dev: false @@ -5287,7 +5210,6 @@ packages: requiresBuild: true dependencies: strnum: 1.0.5 - dev: false optional: true /fast-xml-parser@4.2.7: @@ -5795,7 +5717,6 @@ packages: /ieee754@1.1.13: resolution: {integrity: sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==} - dev: false /ignore-by-default@1.0.1: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} @@ -5827,7 +5748,6 @@ packages: /ip@2.0.0: resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} - dev: false /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} @@ -6429,6 +6349,7 @@ packages: /memory-pager@1.5.0: resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} requiresBuild: true + optional: true /merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} @@ -6577,38 +6498,6 @@ packages: '@mongodb-js/saslprep': 1.1.0 transitivePeerDependencies: - aws-crt - dev: false - - /mongodb@6.2.0: - resolution: {integrity: sha512-d7OSuGjGWDZ5usZPqfvb36laQ9CPhnWkAGHT61x5P95p/8nMVeH8asloMwW6GcYFeB0Vj4CB/1wOTDG2RA9BFA==} - engines: {node: '>=16.20.1'} - peerDependencies: - '@aws-sdk/credential-providers': ^3.188.0 - '@mongodb-js/zstd': ^1.1.0 - gcp-metadata: ^5.2.0 - kerberos: ^2.0.1 - mongodb-client-encryption: '>=6.0.0 <7' - snappy: ^7.2.2 - socks: ^2.7.1 - peerDependenciesMeta: - '@aws-sdk/credential-providers': - optional: true - '@mongodb-js/zstd': - optional: true - gcp-metadata: - optional: true - kerberos: - optional: true - mongodb-client-encryption: - optional: true - snappy: - optional: true - socks: - optional: true - dependencies: - '@mongodb-js/saslprep': 1.1.0 - bson: 6.2.0 - mongodb-connection-string-url: 2.6.0 /mongoose@6.12.0: resolution: {integrity: sha512-sd/q83C6TBRPBrrD2A/POSbA/exbCFM2WOuY7Lf2JuIJFlHFG39zYSDTTAEiYlzIfahNOLmXPxBGFxdAch41Mw==} @@ -7822,7 +7711,6 @@ packages: /smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: false /socket.io-adapter@2.5.2: resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==} @@ -7866,7 +7754,6 @@ packages: dependencies: ip: 2.0.0 smart-buffer: 4.2.0 - dev: false /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -7895,6 +7782,7 @@ packages: requiresBuild: true dependencies: memory-pager: 1.5.0 + optional: true /stack-trace@0.0.10: resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} @@ -7946,7 +7834,6 @@ packages: /strnum@1.0.5: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} requiresBuild: true - dev: false optional: true /stubs@3.0.0: @@ -8175,16 +8062,10 @@ packages: /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} requiresBuild: true - dev: false optional: true - /tslib@2.6.1: - resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} - dev: false - /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: false /type-check@0.3.2: resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} @@ -8359,7 +8240,6 @@ packages: /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - dev: false /uuid@9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} diff --git a/sampleGenerator b/sampleGenerator deleted file mode 160000 index bd4329c1..00000000 --- a/sampleGenerator +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bd4329c15405a09c94e7b78e19ff296b4c2d0fb3 diff --git a/src/modules/stores/mongo.js b/src/modules/stores/mongo.js index f05f266a..695845fc 100755 --- a/src/modules/stores/mongo.js +++ b/src/modules/stores/mongo.js @@ -1,7 +1,6 @@ const mongoose = require("mongoose"); const Schema = mongoose.Schema; -const { mongo: mongoUrl } = require("../../../loadenv"); const logger = require("../logger"); const userSchema = Schema({ @@ -184,23 +183,27 @@ database.on("error", function (err) { logger.error("데이터베이스 연결 에러 발생: " + err); mongoose.disconnect(); }); -database.on("disconnected", function () { - // 데이터베이스 연결이 끊어지면 5초 후 재연결을 시도합니다. - logger.error("데이터베이스와 연결이 끊어졌습니다!"); - setTimeout(() => { - mongoose.connect(mongoUrl, { - useNewUrlParser: true, - useUnifiedTopology: true, - }); - }, 5000); -}); -const connectDatabase = () => +const connectDatabase = (mongoUrl) => { + database.on("disconnected", function () { + // 데이터베이스 연결이 끊어지면 5초 후 재연결을 시도합니다. + logger.error("데이터베이스와 연결이 끊어졌습니다!"); + setTimeout(() => { + mongoose.connect(mongoUrl, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + }, 5000); + }); + mongoose.connect(mongoUrl, { useNewUrlParser: true, useUnifiedTopology: true, }); + return database; +}; + module.exports = { connectDatabase, userModel: mongoose.model("User", userSchema), diff --git a/src/sampleGenerator/.gitignore b/src/sampleGenerator/.gitignore new file mode 100644 index 00000000..2909449b --- /dev/null +++ b/src/sampleGenerator/.gitignore @@ -0,0 +1,107 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and *not* Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# MongoDB Dump +dump/ diff --git a/src/sampleGenerator/README.md b/src/sampleGenerator/README.md new file mode 100644 index 00000000..5afd5960 --- /dev/null +++ b/src/sampleGenerator/README.md @@ -0,0 +1,28 @@ +# taxiSampleGenerator + +이 node 프로그램은 SPARCS-Taxi 프로젝트를 위한 샘플 사용자, 방, 채팅 목록을 생성합니다. +현재 이 프로그램으로 생성된 샘플 채팅 데이터는 입, 퇴장 메시지들과 일반 채팅 메시지들로만 구성되어 있습니다. + +**WARNING** +스크립트 실행 시 기존에 MongoDB에 저장된 사용자, 방, 채팅 정보는 **삭제**됩니다! + +**SETUP** + +1. *(optional)* Root directory의 `.env.test` 파일에 다음 내용을 추가합니다. + ``` + #방과 각각의 방의 채팅 개수 + SAMPLE_NUM_OF_ROOMS=2 + SAMPLE_NUM_OF_CHATS=200 + #채팅 간 최대 시간 간격(단위: 초, 소수도 가능) + SAMPLE_MAXIMUM_INTERVAL_BETWEEN_CHATS=20 + #새로운 채팅이 각각 입/퇴장 메시지일 확률(각각 10%) + SAMPLE_OCCURENCE_OF_JOIN=0.1 + SAMPLE_OCCURENCE_OF_ABORT=0.1 + ``` +1. sampleData.json에 장소, 유저, 방 데이터를 입력합니다. + javascript `User { "id": "sampleId", 사용자 id }` + +1. `pnpm start`로 샘플 채팅 데이터를 만들 수 있습니다. + +1. `pnpm run dumpDB`으로 현재 DB를 덤프할 수 있습니다. +1. `pnpm run restoreDB`로 과거 DB를 덤프 파일로부터 복원할 수 있습니다. diff --git a/src/sampleGenerator/index.js b/src/sampleGenerator/index.js new file mode 100644 index 00000000..e83a9335 --- /dev/null +++ b/src/sampleGenerator/index.js @@ -0,0 +1,47 @@ +const { + generateUser, + generateRoom, + generateSampleLocations, + generateChats, +} = require("./src/testData"); +const { connectDatabase } = require("../modules/stores/mongo"); +const { mongo: mongoUrl, numberOfChats, numberOfRooms } = require("./loadenv"); + +const database = connectDatabase(mongoUrl); + +const fs = require("fs"); +const sampleData = JSON.parse(fs.readFileSync("./sampleData.json")); + +const main = async () => { + await database.db.dropDatabase(); + + const { users, locations } = sampleData; + + const userOids = []; + const roomOids = []; + + for (const [index, user] of users.entries()) { + const userOid = await generateUser(user.id, index + 1, user.isAdmin); + userOids.push(userOid); + } + + const sampleLocationOids = await generateSampleLocations(locations); + + for (const index of Array(numberOfRooms).keys()) { + const roomOid = await generateRoom( + sampleLocationOids, + index + 1, + 7, + userOids[0] + ); //하드코딩: 일주일 뒤에 출발하는 방(들)을 만듭니다. + roomOids.push(roomOid); + } + + for (const roomOid of roomOids) { + await generateChats(roomOid, userOids, numberOfChats); + } + console.log("끝! 스크립트 실행을 중단하셔도 됩니다."); + process.exit(0); +}; + +database.on("open", main); diff --git a/src/sampleGenerator/loadenv.js b/src/sampleGenerator/loadenv.js new file mode 100644 index 00000000..0843789b --- /dev/null +++ b/src/sampleGenerator/loadenv.js @@ -0,0 +1,13 @@ +// Root directory에 있는 .env.test 파일을 읽어옴 +require("dotenv").config({ path: "../../.env.test" }); + +module.exports = { + mongo: process.env.DB_PATH, // required + numberOfRooms: parseInt(process.env.SAMPLE_NUM_OF_ROOMS ?? 2), // optional + numberOfChats: parseInt(process.env.SAMPLE_NUM_OF_CHATS ?? 200), // optional + maximumIntervalBtwChats: parseFloat( + process.env.SAMPLE_MAXIMUM_INTERVAL_BETWEEN_CHATS ?? 20 + ), // optional + occurenceOfJoin: parseFloat(process.env.SAMPLE_OCCURENCE_OF_JOIN ?? 0.1), // optional + occurenceOfAbort: parseFloat(process.env.SAMPLE_OCCURENCE_OF_ABORT ?? 0.1), // optional +}; diff --git a/src/sampleGenerator/package.json b/src/sampleGenerator/package.json new file mode 100644 index 00000000..3c7473bc --- /dev/null +++ b/src/sampleGenerator/package.json @@ -0,0 +1,17 @@ +{ + "name": "taxisamplegenerator", + "version": "1.0.0", + "description": "sample generator", + "main": "index.js", + "scripts": { + "preinstall": "npx only-allow pnpm", + "start": "node index.js", + "test": "echo \"Error: no test specified\" && exit 1", + "dumpDB": "node tools/dump.js", + "restoreDB": "node tools/restore.js" + }, + "keywords": [ + "test" + ], + "license": "ISC" +} diff --git a/src/sampleGenerator/sampleData.json b/src/sampleGenerator/sampleData.json new file mode 100644 index 00000000..546812cd --- /dev/null +++ b/src/sampleGenerator/sampleData.json @@ -0,0 +1,112 @@ +{ + "users": [ + { + "id": "sunday", + "isAdmin": true + }, + { + "id": "monday", + "isAdmin": true + }, + { + "id": "tuesday", + "isAdmin": true + }, + { + "id": "wednesday", + "isAdmin": true + } + ], + "locations": [ + { + "koName": "택시승강장", + "enName": "Taxi Stand", + "longitude": 127.359507, + "latitude": 36.373199 + }, + { + "koName": "대전역", + "enName": "Daejeon Station", + "longitude": 127.434522, + "latitude": 36.331894 + }, + { + "koName": "갤러리아 타임월드", + "enName": "Galleria Timeworld", + "longitude": 127.378188, + "latitude": 36.351938 + }, + { + "koName": "궁동 로데오거리", + "enName": "Gung-dong Rodeo Street", + "longitude": 127.350161, + "latitude": 36.362785 + }, + { + "koName": "대전복합터미널", + "enName": "Daejeon Terminal Complex", + "longitude": 127.350161, + "latitude": 36.362785 + }, + { + "koName": "만년중학교", + "enName": "Mannyon Middle School", + "longitude": 127.375993, + "latitude": 36.366990 + }, + { + "koName": "서대전역", + "enName": "Seodaejeon Station", + "longitude": 127.403933, + "latitude": 36.322517 + }, + { + "koName": "신세계백화점", + "enName": "Shinsegae Department Store", + "longitude": 127.381905, + "latitude": 36.375168 + }, + { + "koName": "오리연못", + "enName": "Duck Pond", + "longitude": 127.362371, + "latitude": 36.367715 + }, + { + "koName": "월평역", + "enName": "Wolpyeong Station", + "longitude": 127.364352, + "latitude": 36.358271 + }, + { + "koName": "유성구청", + "enName": "Yuseong-gu Office", + "longitude": 127.356384, + "latitude": 36.362084 + }, + { + "koName": "유성 고속버스터미널", + "enName": "Yuseong Express Bus Terminal", + "longitude": 127.336467, + "latitude": 36.358279 + }, + { + "koName": "유성 시외버스터미널", + "enName": "Yuseong Intercity Bus Terminal", + "longitude": 127.335971, + "latitude": 36.355604 + }, + { + "koName": "대전청사 고속버스터미널", + "enName": "Government Complex Express Bus Terminal", + "longitude": 127.390504, + "latitude": 36.361462 + }, + { + "koName": "대전청사 시외버스터미널", + "enName": "Government Complex Intercity Bus Terminal", + "longitude": 127.379759, + "latitude": 36.361512 + } + ] +} diff --git a/src/sampleGenerator/src/testData.js b/src/sampleGenerator/src/testData.js new file mode 100644 index 00000000..1209c52a --- /dev/null +++ b/src/sampleGenerator/src/testData.js @@ -0,0 +1,199 @@ +const { + userModel, + roomModel, + locationModel, + chatModel, +} = require("../../modules/stores/mongo"); +const { generateProfileImageUrl } = require("../../modules/modifyProfile"); + +const { + maximumIntervalBtwChats, + occurenceOfJoin, + occurenceOfAbort, +} = require("../loadenv"); + +const generateUser = async (id, num, isAdmin) => { + const newUser = new userModel({ + id: id, + name: `${id}-name`, + nickname: `${id}-nickname`, + profileImageUrl: generateProfileImageUrl(), + joinat: Date.now(), + subinfo: { + kaist: new String(20230000 + num), // ^-^ + sparcs: "", + facebook: "", + twitter: "", + }, + email: `${id}@kaist.ac.kr`, + isAdmin: isAdmin, + }); + await newUser.save(); + return newUser._id; +}; + +const generateSampleLocations = async (locations) => { + if (locations.length === 0) { + console.log("Please provide location(s)!"); + } + + for (const location of locations) { + const locationDocument = new locationModel({ + koName: location.koName, + enName: location.enName, + longitude: location.longitude, + latitude: location.latitude, + }); + await locationDocument.save(); + } + + const locationDocuments = await locationModel.find().lean(); + return locationDocuments.map((locationDocument) => locationDocument._id); +}; + +const generateRoom = async (sampleLocationOids, num, daysAfter, creatorId) => { + const date = new Date(); + date.setDate(date.getDate() + daysAfter); + + let fromIdx = 0; + let toIdx = 0; + + while (fromIdx === toIdx) { + fromIdx = Math.floor(Math.random() * sampleLocationOids.length); + toIdx = Math.floor(Math.random() * sampleLocationOids.length); + } + + const newRoom = new roomModel({ + name: `test-${num}`, + from: sampleLocationOids[fromIdx], + to: sampleLocationOids[toIdx], + time: date, + part: [{ user: creatorId }], + madeat: Date.now(), + maxPartLength: 4, + }); + await newRoom.save(); + return newRoom._id; +}; + +const joinUserToRoom = async (userIdsInRoom, userIdsOutRoom, roomId) => { + // 들어올 사용자를 무작위로 선택 + const authorIdx = Math.floor(Math.random() * userIdsOutRoom.length); + const userOid = userIdsOutRoom[authorIdx]; + + // 방, 유저 상태 갱신 + userIdsInRoom.push(userOid); + userIdsOutRoom.splice(authorIdx, 1); + const user = await userModel.findById(userOid, "ongoingRoom"); + user.ongoingRoom.push(roomId); + await user.save(); + + return { userIdsInRoom, userIdsOutRoom, userOid }; +}; + +const abortUserfromRoom = async (userIdsInRoom, userIdsOutRoom, roomId) => { + // 나갈 사용자를 무작위로 선택 + const authorIdx = Math.floor(Math.random() * userIdsInRoom.length); + const userOid = userIdsInRoom[authorIdx]; + + // 방, 유저 상태 갱신 + userIdsOutRoom.push(userOid); + userIdsInRoom.splice(authorIdx, 1); + const user = await userModel.findById(userOid, "ongoingRoom"); + user.ongoingRoom.splice(user.ongoingRoom.indexOf(roomId), 1); + await user.save(); + + return { userIdsInRoom, userIdsOutRoom, userOid }; +}; + +const generateNormalChat = async (i, roomId, userOid, time) => { + const user = await userModel.findById(userOid); + const newChat = new chatModel({ + roomId: roomId, + type: "text", + authorId: user._id, + content: `안녕하세요! (${i}번째 메시지)`, + time: time, + inValid: false, + }); + await newChat.save(); +}; + +const generateJoinAbortChat = async (roomId, userOid, isJoining, time) => { + const user = await userModel.findById(userOid); + const newChat = new chatModel({ + roomId: roomId, + type: isJoining ? "in" : "out", + authorId: user._id, + content: user.id, + time: time, + isValid: false, + }); + await newChat.save(); +}; + +const generateChats = async (roomId, userOids, numOfChats) => { + const roomPopulateQuery = [{ path: "part", select: "id name nickname -_id" }]; + const room = await roomModel.findById(roomId).populate(roomPopulateQuery); + + let userIdsInRoom = []; + let userIdsOutRoom = userOids.map((userOid) => userOid); + let lastTime = Date.now(); + const maximumIntervalBtwChatsMilliseconds = 1000 * maximumIntervalBtwChats; + + for (const i of Array(numOfChats).keys()) { + lastTime += Math.floor(Math.random() * maximumIntervalBtwChatsMilliseconds); + const event = Math.random(); + + if ( + userIdsInRoom.length === 0 || + (event < occurenceOfJoin && userIdsOutRoom.length !== 0) + ) { + // 더 들어올 사용자가 있을 경우, 더 들어옴 + // 방, 유저 상태 갱신 + let userOid; + ({ userIdsInRoom, userIdsOutRoom, userOid } = await joinUserToRoom( + userIdsInRoom, + userIdsOutRoom, + roomId + )); + // 입장 메시지 생성 + await generateJoinAbortChat(roomId, userOid, true, lastTime); + } else if ( + occurenceOfJoin <= event && + event < occurenceOfJoin + occurenceOfAbort && + userIdsInRoom.length > 1 + ) { + // 나갈 사용자가 있을 경우, 나감 + // 방, 유저 상태 갱신 + let userOid; + ({ userIdsInRoom, userIdsOutRoom, userOid } = await abortUserfromRoom( + userIdsInRoom, + userIdsOutRoom, + roomId + )); + // 퇴장 메시지 생성 + await generateJoinAbortChat(roomId, userOid, false, lastTime); + } else { + // 방이 비어있지 않을 경우, 일반 채팅 메시지를 만듦 + if (userIdsInRoom.length !== 0) { + const authorIdx = Math.floor(Math.random() * userIdsInRoom.length); + const user = userIdsInRoom[authorIdx]; + await generateNormalChat(i, roomId, user, lastTime); + } + } + } + // 현재 참여중인 사용자 기준으로 방의 part 리스트를 업데이트함 + room.part = userIdsInRoom.map((userOid) => { + return { user: userOid }; + }); + await room.save(); + return; +}; + +module.exports = { + generateUser, + generateRoom, + generateSampleLocations, + generateChats, +}; diff --git a/src/sampleGenerator/tools/dump.js b/src/sampleGenerator/tools/dump.js new file mode 100644 index 00000000..7d26d802 --- /dev/null +++ b/src/sampleGenerator/tools/dump.js @@ -0,0 +1,20 @@ +const util = require("util"); +const path = require("path"); +const exec = util.promisify(require("child_process").exec); +const { mongo: mongoUrl } = require("../loadenv"); + +const main = async () => { + const { stdout, stderr } = await exec( + `mongodump ${mongoUrl} --out ${path.resolve("dump")}` + ); + console.log("dump 디렉토리에 데이터베이스 데이터를 덤프했습니다."); + process.exit(0); +}; + +try { + main(); +} catch { + console.log( + "DB 연결 주소가 올바르지 않습니다. DB 연결 주소를 다시 한 번 확인해주세요." + ); +} diff --git a/src/sampleGenerator/tools/restore.js b/src/sampleGenerator/tools/restore.js new file mode 100644 index 00000000..5c14c98b --- /dev/null +++ b/src/sampleGenerator/tools/restore.js @@ -0,0 +1,23 @@ +const util = require("util"); +const path = require("path"); +const exec = util.promisify(require("child_process").exec); +const { mongo: mongoUrl } = require("../loadenv"); + +const main = async () => { + const dbName = mongoUrl.split("/").pop(); + const { stdout, stderr } = await exec( + `mongorestore ${mongoUrl} ${path.resolve("dump", dbName)}` + ); + console.log( + "dump 디렉토리로부터 데이터베이스 정보를 성공적으로 복원했습니다." + ); + process.exit(0); +}; + +try { + main(); +} catch { + console.log( + "DB를 덤프해올 디렉토리가 존재하지 않습니다. 경로를 다시 한 번 확인해주세요." + ); +} diff --git a/test/utils.js b/test/utils.js index b3920e83..e537913b 100644 --- a/test/utils.js +++ b/test/utils.js @@ -7,8 +7,9 @@ const { connectDatabase, } = require("../src/modules/stores/mongo"); const { generateProfileImageUrl } = require("../src/modules/modifyProfile"); +const { mongo: mongoUrl } = require("../loadenv"); -connectDatabase(); +connectDatabase(mongoUrl); // 테스트를 위한 유저 생성 함수 const userGenerator = async (username, testData) => {