From cc1bc43dff8c9a5e953fc393e4fa9d656c38c99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Ti=E1=BA=BFn=20T=C3=A0i?= <63393170+fdhhhdjd@users.noreply.github.com> Date: Wed, 15 Mar 2023 01:06:55 +0700 Subject: [PATCH] #180 hotfix book tai dev 20230315 --- .../admin.controllers/admin.controller.js | 16 +-- .../author.controllers/author.controller.js | 8 +- .../book.controllers/book.controller.js | 6 +- .../borrow_book.controller.js | 4 +- .../src/share/configs/constants.js | 9 ++ .../src/share/db/init_multiple_redis.js | 4 + .../src/share/middleware/handle_error.js | 3 +- .../src/share/models/author.model.js | 35 +++-- .../src/share/models/book.model.js | 35 +++-- .../src/share/models/book_borrowed.model.js | 134 +++++++++--------- .../src/share/models/categories.model.js | 42 +++--- .../src/share/models/phone.model.js | 35 +++-- .../src/share/models/user.model.js | 42 +++--- .../src/share/models/user_device.model.js | 69 +++++---- .../share/models/user_reset_password.model.js | 65 ++++----- .../share/models/user_verification.model.js | 69 +++++---- .../share/patterns/LRU_Strategy.patterns.js | 5 +- .../services/admin_service/book_service.js | 5 + .../src/share/utils/helper.js | 3 +- .../src/share/utils/limited_redis.js | 23 ++- .../src/share/utils/redis_cluster_helper.js | 19 ++- .../src/share/utils/redis_pub_sub_helper.js | 12 ++ backend-manager-student/src/user_api/app.js | 3 + .../book.controllers/book.controller.js | 24 ++-- .../borrow_book.controller.js | 18 +-- .../user.controllers/user.controller.js | 12 +- .../user_api/v1/queue/book_user/book.user.js | 29 ++++ .../src/user_api/v1/queue/queue_redis.js | 51 +++++++ .../src/user_api/v1/routes/index.router.js | 9 +- 29 files changed, 447 insertions(+), 342 deletions(-) create mode 100644 backend-manager-student/src/user_api/v1/queue/book_user/book.user.js create mode 100644 backend-manager-student/src/user_api/v1/queue/queue_redis.js diff --git a/backend-manager-student/src/admin_api/v1/controllers/admin.controllers/admin.controller.js b/backend-manager-student/src/admin_api/v1/controllers/admin.controllers/admin.controller.js index c7d56a3..f01cb2a 100644 --- a/backend-manager-student/src/admin_api/v1/controllers/admin.controllers/admin.controller.js +++ b/backend-manager-student/src/admin_api/v1/controllers/admin.controllers/admin.controller.js @@ -116,8 +116,8 @@ const adminController = { sameSite: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, secure: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, domain: - CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT - ? req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] + CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? + req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] : CONSTANTS.HEADER_DOMAIN, maxAge: CONSTANTS._1_MONTH, }); @@ -261,8 +261,8 @@ const adminController = { sameSite: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, secure: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, domain: - CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT - ? req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] + CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? + req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] : CONSTANTS.HEADER_DOMAIN, maxAge: CONSTANTS._1_MONTH, }); @@ -432,12 +432,12 @@ const adminController = { class: student.class, email: student.email, gender: - student.gender.toLowerCase() === CONSTANTS.GENDER_MALE_STRING - ? CONSTANTS.GENDER_MALE + student.gender.toLowerCase() === CONSTANTS.GENDER_MALE_STRING ? + CONSTANTS.GENDER_MALE : CONSTANTS.GENDER_FEMALE, avatar_uri: - student.gender.toLowerCase() === CONSTANTS.GENDER_MALE_STRING - ? CONSTANTS.GENDER_IMAGE_MALE + student.gender.toLowerCase() === CONSTANTS.GENDER_MALE_STRING ? + CONSTANTS.GENDER_IMAGE_MALE : CONSTANTS.GENDER_IMAGE_FEMALE, }); } diff --git a/backend-manager-student/src/admin_api/v1/controllers/author.controllers/author.controller.js b/backend-manager-student/src/admin_api/v1/controllers/author.controllers/author.controller.js index fab4069..e301e16 100644 --- a/backend-manager-student/src/admin_api/v1/controllers/author.controllers/author.controller.js +++ b/backend-manager-student/src/admin_api/v1/controllers/author.controllers/author.controller.js @@ -17,7 +17,9 @@ const authorController = { * @return {Object:{Number,String} */ createAuthor: async (req, res) => { - const { name, avatar_uri, dob, gender } = req.body.input.author_input; + const { + name, avatar_uri, dob, gender, + } = req.body.input.author_input; // Check input if (!name || !avatar_uri || !dob || !gender) { @@ -72,7 +74,9 @@ const authorController = { * @return {Object:{Number,String} */ updateAuthor: async (req, res) => { - const { author_id, name, avatar_uri, dob, gender } = req.body.input.author_input; + const { + author_id, name, avatar_uri, dob, gender, + } = req.body.input.author_input; // Check input if (!author_id) { diff --git a/backend-manager-student/src/admin_api/v1/controllers/book.controllers/book.controller.js b/backend-manager-student/src/admin_api/v1/controllers/book.controllers/book.controller.js index e8779a3..2baebdf 100644 --- a/backend-manager-student/src/admin_api/v1/controllers/book.controllers/book.controller.js +++ b/backend-manager-student/src/admin_api/v1/controllers/book.controllers/book.controller.js @@ -23,8 +23,10 @@ const bookController = { * @return {Object:{Number,String} */ createBook: async (req, res) => { - const { name, author_id, image_uri, description, bookshelf, language, quantity, public_id_image } = - req.body.input.author_input; + const { + name, author_id, image_uri, description, bookshelf, language, quantity, public_id_image, + } + = req.body.input.author_input; // Check input if ( diff --git a/backend-manager-student/src/admin_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js b/backend-manager-student/src/admin_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js index b200150..10b9597 100644 --- a/backend-manager-student/src/admin_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js +++ b/backend-manager-student/src/admin_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js @@ -21,7 +21,9 @@ const BorrowBookController = { * @return {Object:{Number,String} */ updateBorrowBook: async (req, res) => { - const { book_id, user_id, start_date, due_date, status } = req.body.input.borrow_book_input; + const { + book_id, user_id, start_date, due_date, status, + } = req.body.input.borrow_book_input; // Check input if (!book_id || !user_id || !start_date || !due_date || !status) { diff --git a/backend-manager-student/src/share/configs/constants.js b/backend-manager-student/src/share/configs/constants.js index d4457a2..3739123 100644 --- a/backend-manager-student/src/share/configs/constants.js +++ b/backend-manager-student/src/share/configs/constants.js @@ -357,4 +357,13 @@ module.exports = { */ YES: 1, NO: 0, + /** + * @author Nguyễn Tiến Tài + * @created_at 15/03/2023 + * @description Key Redis General + * @param { String } + */ + // Student + KEY_USER_EXIT_U: 'user_api*', + DELETE_KEY_CACHE_LRU: 'user_api_delete_key_lru', }; diff --git a/backend-manager-student/src/share/db/init_multiple_redis.js b/backend-manager-student/src/share/db/init_multiple_redis.js index 327ac74..5fa7f57 100644 --- a/backend-manager-student/src/share/db/init_multiple_redis.js +++ b/backend-manager-student/src/share/db/init_multiple_redis.js @@ -1,9 +1,13 @@ +//! LIBRARY const IOREDIS = require('ioredis'); + +//! SHARE const CONFIGS = require('../configs/config'); /** * @author Nguyễn Tiến Tài * @created_at 22/01/2023 + * @updated_at 15/03/2023 * @description Connect Cache Redis Master and Slave */ const ConnectionRedis = (REDIS) => { diff --git a/backend-manager-student/src/share/middleware/handle_error.js b/backend-manager-student/src/share/middleware/handle_error.js index b2ff6c3..13e03e3 100644 --- a/backend-manager-student/src/share/middleware/handle_error.js +++ b/backend-manager-student/src/share/middleware/handle_error.js @@ -9,6 +9,5 @@ module.exports = { * @param { code } * @return { String } */ - returnReasons: (code) => - CONSTANTS.reasonPhraseCodeProNewMap().get(code) || CONSTANTS.reasonPhraseCodeProNewMap().get('default'), + returnReasons: (code) => CONSTANTS.reasonPhraseCodeProNewMap().get(code) || CONSTANTS.reasonPhraseCodeProNewMap().get('default'), }; diff --git a/backend-manager-student/src/share/models/author.model.js b/backend-manager-student/src/share/models/author.model.js index 776a75c..eae7424 100644 --- a/backend-manager-student/src/share/models/author.model.js +++ b/backend-manager-student/src/share/models/author.model.js @@ -7,15 +7,15 @@ module.exports = { * @created_at 03/01/2023 * @description create Author */ - createAuthor: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('authors').insert(data).onConflict('author_id').merge().returning(['author_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + createAuthor: (data) => new Promise((resolve, reject) => { + try { + const result = knex('authors').insert(data).onConflict('author_id').merge() + .returning(['author_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài @@ -31,15 +31,14 @@ module.exports = { * @created_at 03/01/2023 * @description Update Author */ - updateAuthor: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('authors').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateAuthor: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('authors').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 01/03/2023 diff --git a/backend-manager-student/src/share/models/book.model.js b/backend-manager-student/src/share/models/book.model.js index 776e383..a404835 100644 --- a/backend-manager-student/src/share/models/book.model.js +++ b/backend-manager-student/src/share/models/book.model.js @@ -7,15 +7,15 @@ module.exports = { * @created_at 03/01/2023 * @description create book */ - createBook: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('books').insert(data).onConflict('book_id').merge().returning(['book_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + createBook: (data) => new Promise((resolve, reject) => { + try { + const result = knex('books').insert(data).onConflict('book_id').merge() + .returning(['book_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài @@ -31,15 +31,14 @@ module.exports = { * @created_at 03/01/2023 * @description Update book */ - updateBook: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('books').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateBook: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('books').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 03/01/2023 diff --git a/backend-manager-student/src/share/models/book_borrowed.model.js b/backend-manager-student/src/share/models/book_borrowed.model.js index ceb06e7..6c54ad7 100644 --- a/backend-manager-student/src/share/models/book_borrowed.model.js +++ b/backend-manager-student/src/share/models/book_borrowed.model.js @@ -10,19 +10,18 @@ module.exports = { * @created_at 07/03/2023 * @description create BorrowBook */ - createBorrowBook: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('borrowed_book') - .insert(data) - .onConflict('borrowed_book_id') - .merge() - .returning(['borrowed_book_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + createBorrowBook: (data) => new Promise((resolve, reject) => { + try { + const result = knex('borrowed_book') + .insert(data) + .onConflict('borrowed_book_id') + .merge() + .returning(['borrowed_book_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài @@ -38,15 +37,14 @@ module.exports = { * @created_at 07/03/2023 * @description Update BorrowBook */ - updateBorrowBook: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('borrowed_book').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateBorrowBook: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('borrowed_book').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 07/03/2023 @@ -79,62 +77,60 @@ module.exports = { * @created_at 07/03/2023 * @description Transaction Update Borrow Book */ - transactionUpdateBorrowBook: async (data_update_book, data_update_borrow) => - new Promise(async (resolve, reject) => { - // start transaction - const trx = await knex.transaction(); - try { - // Query 1: createBorrowBook - const borrowBookId = await trx('borrowed_book') - .update({ status: data_update_borrow.status }) - .where({ book_id: data_update_borrow.book_id, user_id: data_update_borrow.user_id }) - .returning(['borrowed_book_id']); + transactionUpdateBorrowBook: async (data_update_book, data_update_borrow) => new Promise(async (resolve, reject) => { + // start transaction + const trx = await knex.transaction(); + try { + // Query 1: createBorrowBook + const borrowBookId = await trx('borrowed_book') + .update({ status: data_update_borrow.status }) + .where({ book_id: data_update_borrow.book_id, user_id: data_update_borrow.user_id }) + .returning(['borrowed_book_id']); - // Query 2: updateBorrowBook - const updatedData = await trx('books') - .update({ quantity: data_update_book.quantity }) - .where({ book_id: data_update_book.book_id }) - .returning(['book_id']); + // Query 2: updateBorrowBook + const updatedData = await trx('books') + .update({ quantity: data_update_book.quantity }) + .where({ book_id: data_update_book.book_id }) + .returning(['book_id']); - // Commit transaction - await trx.commit(); - return resolve(borrowBookId, updatedData); - } catch (error) { - trx.rollback(); - reject(error); - } - }), + // Commit transaction + await trx.commit(); + return resolve(borrowBookId, updatedData); + } catch (error) { + trx.rollback(); + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 08/03/2023 * @description Transaction Borrow Book */ - transactionBorrowBook: async (data_insert, data_update) => - new Promise(async (resolve, reject) => { - // start transaction - const trx = await knex.transaction(); - try { - // Query 1: createBorrowBook - const borrowBookId = await trx('borrowed_book') - .insert(data_insert) - .onConflict('borrowed_book_id') - .merge() - .returning(['borrowed_book_id']); + transactionBorrowBook: async (data_insert, data_update) => new Promise(async (resolve, reject) => { + // start transaction + const trx = await knex.transaction(); + try { + // Query 1: createBorrowBook + const borrowBookId = await trx('borrowed_book') + .insert(data_insert) + .onConflict('borrowed_book_id') + .merge() + .returning(['borrowed_book_id']); - // Query 2: updateBorrowBook - const updatedData = await trx('books') - .update(data_update) - .where({ book_id: data_insert.book_id }) - .returning(['book_id']); + // Query 2: updateBorrowBook + const updatedData = await trx('books') + .update(data_update) + .where({ book_id: data_insert.book_id }) + .returning(['book_id']); - // Commit transaction - await trx.commit(); - return resolve(borrowBookId, updatedData); - } catch (error) { - trx.rollback(); - reject(error); - } - }), + // Commit transaction + await trx.commit(); + return resolve(borrowBookId, updatedData); + } catch (error) { + trx.rollback(); + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 09/03/2023 diff --git a/backend-manager-student/src/share/models/categories.model.js b/backend-manager-student/src/share/models/categories.model.js index 8a1ceb8..29ce4ac 100644 --- a/backend-manager-student/src/share/models/categories.model.js +++ b/backend-manager-student/src/share/models/categories.model.js @@ -7,19 +7,18 @@ module.exports = { * @created_at 03/02/2023 * @description create Categories */ - createCategories: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('categories') - .insert(data) - .onConflict('category_id') - .merge() - .returning(['category_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + createCategories: (data) => new Promise((resolve, reject) => { + try { + const result = knex('categories') + .insert(data) + .onConflict('category_id') + .merge() + .returning(['category_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài @@ -35,15 +34,14 @@ module.exports = { * @created_at 03/02/2023 * @description Update Categories */ - updateCategories: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('categories').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateCategories: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('categories').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 03/02/2023 diff --git a/backend-manager-student/src/share/models/phone.model.js b/backend-manager-student/src/share/models/phone.model.js index c46c101..786d3e2 100644 --- a/backend-manager-student/src/share/models/phone.model.js +++ b/backend-manager-student/src/share/models/phone.model.js @@ -7,15 +7,15 @@ module.exports = { * @created_at 09/03/2023 * @description create Phone */ - createPhone: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('phone').insert(data).onConflict('phone_id').merge().returning(['phone_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + createPhone: (data) => new Promise((resolve, reject) => { + try { + const result = knex('phone').insert(data).onConflict('phone_id').merge() + .returning(['phone_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @Phone Nguyễn Tiến Tài @@ -31,13 +31,12 @@ module.exports = { * @created_at 09/03/2023 * @description Update Phone */ - updatePhone: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('phone').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updatePhone: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('phone').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), }; diff --git a/backend-manager-student/src/share/models/user.model.js b/backend-manager-student/src/share/models/user.model.js index 8217b5e..db27053 100644 --- a/backend-manager-student/src/share/models/user.model.js +++ b/backend-manager-student/src/share/models/user.model.js @@ -11,19 +11,18 @@ module.exports = { * @update_at 23/01/2022 * @description Add user */ - addUser: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('user') - .insert(data) - .onConflict('user_id', 'email', 'phone_number', 'mssv') - .merge() - .returning(['user_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + addUser: (data) => new Promise((resolve, reject) => { + try { + const result = knex('user') + .insert(data) + .onConflict('user_id', 'email', 'phone_number', 'mssv') + .merge() + .returning(['user_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài @@ -39,15 +38,14 @@ module.exports = { * @created_at 13/02/2023 * @description Update student */ - updateStudent: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('user').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateStudent: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('user').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 28/02/2023 diff --git a/backend-manager-student/src/share/models/user_device.model.js b/backend-manager-student/src/share/models/user_device.model.js index 1323935..8b304b0 100644 --- a/backend-manager-student/src/share/models/user_device.model.js +++ b/backend-manager-student/src/share/models/user_device.model.js @@ -10,52 +10,49 @@ module.exports = { * @created_at 03/02/2023 * @description insertDevice */ - insertDevice: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('user_device') - .insert(data) - .onConflict('device_uuid') - .merge() - .returning(['device_uuid']); - resolve(result); - } catch (error) { - reject(error); - } - }), + insertDevice: (data) => new Promise((resolve, reject) => { + try { + const result = knex('user_device') + .insert(data) + .onConflict('device_uuid') + .merge() + .returning(['device_uuid']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 03/02/2023 * @description insertDevice */ - checkUserByToken: (refresh_token, device_uuid) => - new Promise((resolve, reject) => { - try { - let user = knex('user_device') - .join('user', 'user.user_id', 'user_device.user_id') - .where('user.isdeleted', '=', CONSTANTS.DELETED_DISABLE) - .andWhere('user_device.refresh_token', refresh_token) - .andWhere('user_device.device_uuid', device_uuid) - .select('user.user_id', 'user.role', 'user.name', 'user.email', 'user.role'); - resolve(user); - } catch (error) { - reject(error); - } - }), + checkUserByToken: (refresh_token, device_uuid) => new Promise((resolve, reject) => { + try { + let user = knex('user_device') + .join('user', 'user.user_id', 'user_device.user_id') + .where('user.isdeleted', '=', CONSTANTS.DELETED_DISABLE) + .andWhere('user_device.refresh_token', refresh_token) + .andWhere('user_device.device_uuid', device_uuid) + .select('user.user_id', 'user.role', 'user.name', 'user.email', 'user.role'); + resolve(user); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 05/02/2023 * @description updateDevice */ - updateDevice: (data, user) => - new Promise((resolve, reject) => { - try { - const result = knex('user_device').where('user_id', user).update(data).returning(['device_uuid']); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateDevice: (data, user) => new Promise((resolve, reject) => { + try { + const result = knex('user_device').where('user_id', user).update(data).returning(['device_uuid']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 15/02/2023 diff --git a/backend-manager-student/src/share/models/user_reset_password.model.js b/backend-manager-student/src/share/models/user_reset_password.model.js index 98f7647..5e80afb 100644 --- a/backend-manager-student/src/share/models/user_reset_password.model.js +++ b/backend-manager-student/src/share/models/user_reset_password.model.js @@ -10,19 +10,18 @@ module.exports = { * @created_at 23/02/2023 * @description Insert reset password student */ - insertResetPassword: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('reset_password') - .insert(data) - .onConflict('id') - .merge() - .returning(['id', 'user_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + insertResetPassword: (data) => new Promise((resolve, reject) => { + try { + const result = knex('reset_password') + .insert(data) + .onConflict('id') + .merge() + .returning(['id', 'user_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 24/02/2023 @@ -37,31 +36,29 @@ module.exports = { * @created_at 24/02/2023 * @description Update reset Password */ - updateResetPassword: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('reset_password').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateResetPassword: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('reset_password').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 28/02/2023 * @description List all reset password */ - getResetPasswordList: async () => - new Promise((resolve, reject) => { - knex('reset_password') - .where('isdeleted', CONSTANTS.DELETED_DISABLE) - .orderBy('created_at', 'asc') - .then((result) => { - resolve(result); - }) - .catch((err) => { - reject(err); - }); - }), + getResetPasswordList: async () => new Promise((resolve, reject) => { + knex('reset_password') + .where('isdeleted', CONSTANTS.DELETED_DISABLE) + .orderBy('created_at', 'asc') + .then((result) => { + resolve(result); + }) + .catch((err) => { + reject(err); + }); + }), }; diff --git a/backend-manager-student/src/share/models/user_verification.model.js b/backend-manager-student/src/share/models/user_verification.model.js index aadf783..e59edc4 100644 --- a/backend-manager-student/src/share/models/user_verification.model.js +++ b/backend-manager-student/src/share/models/user_verification.model.js @@ -10,19 +10,18 @@ module.exports = { * @created_at 25/02/2023 * @description Insert reset verification student */ - insertVerificationEmail: (data) => - new Promise((resolve, reject) => { - try { - const result = knex('verification') - .insert(data) - .onConflict('verify_id') - .merge() - .returning(['verify_id']); - resolve(result); - } catch (error) { - reject(error); - } - }), + insertVerificationEmail: (data) => new Promise((resolve, reject) => { + try { + const result = knex('verification') + .insert(data) + .onConflict('verify_id') + .merge() + .returning(['verify_id']); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài @@ -38,32 +37,30 @@ module.exports = { * @created_at 26/02/2023 * @description Update verification */ - updateVerification: async (data, student_query, return_data) => - new Promise((resolve, reject) => { - try { - const result = knex('verification').update(data).where(student_query).returning(return_data); - resolve(result); - } catch (error) { - reject(error); - } - }), + updateVerification: async (data, student_query, return_data) => new Promise((resolve, reject) => { + try { + const result = knex('verification').update(data).where(student_query).returning(return_data); + resolve(result); + } catch (error) { + reject(error); + } + }), /** * @author Nguyễn Tiến Tài * @created_at 26/02/2023 * @description Update verification */ - getVerificationList: async () => - new Promise((resolve, reject) => { - knex('verification') - .where('isdeleted', CONSTANTS.DELETED_DISABLE) - .where('verified', CONSTANTS.DELETED_DISABLE) - .where('check_login', CONSTANTS.DELETED_DISABLE) - .orderBy('created_at', 'asc') - .then((result) => { - resolve(result); - }) - .catch((err) => { - reject(err); - }); - }), + getVerificationList: async () => new Promise((resolve, reject) => { + knex('verification') + .where('isdeleted', CONSTANTS.DELETED_DISABLE) + .where('verified', CONSTANTS.DELETED_DISABLE) + .where('check_login', CONSTANTS.DELETED_DISABLE) + .orderBy('created_at', 'asc') + .then((result) => { + resolve(result); + }) + .catch((err) => { + reject(err); + }); + }), }; diff --git a/backend-manager-student/src/share/patterns/LRU_Strategy.patterns.js b/backend-manager-student/src/share/patterns/LRU_Strategy.patterns.js index 9b18716..0b04275 100644 --- a/backend-manager-student/src/share/patterns/LRU_Strategy.patterns.js +++ b/backend-manager-student/src/share/patterns/LRU_Strategy.patterns.js @@ -60,8 +60,9 @@ class LRUCache { delMultiCache(key_1, key_2) { try { - this._cache.delete(key_1) && this._cache.delete(key_2); - return true; + const deleted_1 = this._cache.delete(key_1); + const deleted_2 = this._cache.delete(key_2); + return deleted_1 && deleted_2; } catch (error) { throw new Error(`Error deleting key ${key_1} and ${key_2} from cache: ${error}`); } diff --git a/backend-manager-student/src/share/services/admin_service/book_service.js b/backend-manager-student/src/share/services/admin_service/book_service.js index 6832f59..5a4bfde 100644 --- a/backend-manager-student/src/share/services/admin_service/book_service.js +++ b/backend-manager-student/src/share/services/admin_service/book_service.js @@ -1,6 +1,7 @@ //! SHARE const MEMORY_CACHE = require('../../utils/limited_redis'); const CONSTANTS = require('../../configs/constants'); +const REDIS_PUB_SUB = require('../../utils/redis_pub_sub_helper'); //! MIDDLEWARE const { globalCache } = require('../../patterns/LRU_Strategy.patterns'); @@ -20,6 +21,10 @@ module.exports = { // Delete data cache lru argothim globalCache.delCache(key_cache_lru); } + // Publish data queue Redis + REDIS_PUB_SUB.queueMessageUserApi(CONSTANTS.DELETE_KEY_CACHE_LRU, { + result: key_cache_lru, + }); // Check key Redis const check_key_redis_book_all = await MEMORY_CACHE.existsKeyCache(key_cache_redis); diff --git a/backend-manager-student/src/share/utils/helper.js b/backend-manager-student/src/share/utils/helper.js index 0dfa175..c70a261 100644 --- a/backend-manager-student/src/share/utils/helper.js +++ b/backend-manager-student/src/share/utils/helper.js @@ -159,8 +159,7 @@ module.exports = { * @description Mobile network * @returns {String} */ - returnMobileNetWork: (code) => - CONSTANTS.mobileCodeProNewMap().get(code) || CONSTANTS.mobileCodeProNewMap().get('default'), + returnMobileNetWork: (code) => CONSTANTS.mobileCodeProNewMap().get(code) || CONSTANTS.mobileCodeProNewMap().get('default'), /** * @author Nguyễn Tiến Tài * @created_at 20/01/2023 diff --git a/backend-manager-student/src/share/utils/limited_redis.js b/backend-manager-student/src/share/utils/limited_redis.js index f1d7978..8c2072f 100644 --- a/backend-manager-student/src/share/utils/limited_redis.js +++ b/backend-manager-student/src/share/utils/limited_redis.js @@ -39,18 +39,17 @@ const getRangeCache = (key, start, end) => REDIS_MASTER.lrange(key, start, end); * @description Set multi * @returns {Array} */ -const setBlackListCache = (key, user_id, accept_token, refresh_token, ttl) => - REDIS_MASTER.multi() - .lpush(key, accept_token, refresh_token) - .del(user_id) - .expire(key, ttl) - .exec((err, replies) => { - if (err) { - console.error(err); - } else { - console.info(replies); - } - }); +const setBlackListCache = (key, user_id, accept_token, refresh_token, ttl) => REDIS_MASTER.multi() + .lpush(key, accept_token, refresh_token) + .del(user_id) + .expire(key, ttl) + .exec((err, replies) => { + if (err) { + console.error(err); + } else { + console.info(replies); + } + }); /** * @author Nguyễn Tiến Tài * @param {key} diff --git a/backend-manager-student/src/share/utils/redis_cluster_helper.js b/backend-manager-student/src/share/utils/redis_cluster_helper.js index fbb19a3..4e278f2 100644 --- a/backend-manager-student/src/share/utils/redis_cluster_helper.js +++ b/backend-manager-student/src/share/utils/redis_cluster_helper.js @@ -7,17 +7,16 @@ const { REDIS_MASTER, REDIS_SLAVE } = require('../db/init_multiple_redis'); * @param {REDIS_MASTER OR REDIS_SLAVE,String} * @return {resolve or reject} */ -const getDataWithTimeout = async (redisClient, key) => - await new Promise((resolve, reject) => { - redisClient.get(key, (error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); - setTimeout(() => reject(new Error('Timeout')), 3000); +const getDataWithTimeout = async (redisClient, key) => await new Promise((resolve, reject) => { + redisClient.get(key, (error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } }); + setTimeout(() => reject(new Error('Timeout')), 3000); +}); /** * @author Nguyễn Tiến Tài diff --git a/backend-manager-student/src/share/utils/redis_pub_sub_helper.js b/backend-manager-student/src/share/utils/redis_pub_sub_helper.js index 6bf1981..625fa7f 100644 --- a/backend-manager-student/src/share/utils/redis_pub_sub_helper.js +++ b/backend-manager-student/src/share/utils/redis_pub_sub_helper.js @@ -42,6 +42,18 @@ const sendEmailWithLock = async (key, value) => { throw new Error('Cannot acquire lock.'); } }; +const queueMessageUserApi = async (key, value) => { + const key_convert = key; + const value_convert = JSON.stringify(value); + try { + // send email here + const publishResult = await REDIS_MASTER.publish(key_convert, value_convert); + console.info(`Published to ${publishResult} subscribers.`); + } finally { + console.info('Del success'); + } +}; module.exports = { sendEmailWithLock, + queueMessageUserApi, }; diff --git a/backend-manager-student/src/user_api/app.js b/backend-manager-student/src/user_api/app.js index 43d88b0..a38e278 100644 --- a/backend-manager-student/src/user_api/app.js +++ b/backend-manager-student/src/user_api/app.js @@ -87,4 +87,7 @@ app.use(DEVICE_MIDDLEWARE); //! ROUTE app.use(USER_API); +//! REDIS PUBSUB +require('./v1/queue/queue_redis'); + module.exports = app; diff --git a/backend-manager-student/src/user_api/v1/controllers/book.controllers/book.controller.js b/backend-manager-student/src/user_api/v1/controllers/book.controllers/book.controller.js index def02cd..101c407 100644 --- a/backend-manager-student/src/user_api/v1/controllers/book.controllers/book.controller.js +++ b/backend-manager-student/src/user_api/v1/controllers/book.controllers/book.controller.js @@ -1,13 +1,14 @@ //! SHARE const HELPER = require('../../../../share/utils/helper'); const CONSTANTS = require('../../../../share/configs/constants'); - +const RANDOMS = require('../../../../share/utils/random'); +const MEMORY_CACHE = require('../../../../share/utils/limited_redis'); //! MIDDLEWARE const { globalCache } = require('../../../../share/patterns/LRU_Strategy.patterns'); const { returnReasons } = require('../../../../share/middleware/handle_error'); - //! MODEL const book_model = require('../../../../share/models/book.model'); +const book_admin_service = require('../../../../share/services/admin_service/book_service'); const bookController = { /** @@ -52,7 +53,7 @@ const bookController = { if (result_book_detail) { // Add data cache lru argothim - globalCache.putCache(key_cache_book_detail, result_book_detail[0]); + book_admin_service.handleSetCacheLRU(key_cache_book_detail, result_book_detail[0]); return res.status(200).json({ status: 200, @@ -81,14 +82,14 @@ const bookController = { */ getAllBook: async (req, res) => { try { - // detail book database - const cache_lru_book = globalCache.getCache(CONSTANTS.KEY_REDIS.ALL_BOOK); - if (cache_lru_book !== CONSTANTS.NO) { + // Detail book database + const cache_redis_book = await MEMORY_CACHE.getCache(CONSTANTS.KEY_REDIS.ALL_BOOK); + if (cache_redis_book) { return res.status(200).json({ status: 200, message: returnReasons('200'), element: { - result: cache_lru_book, + result: JSON.parse(cache_redis_book), }, }); } @@ -96,8 +97,13 @@ const bookController = { // Take data db const result_book = await book_model.getAllBook({ isdeleted: CONSTANTS.DELETED_DISABLE }, '*'); if (result_book) { - // Add data cache lru argothim - globalCache.putCache(CONSTANTS.KEY_REDIS.ALL_BOOK, result_book); + const redisTTLWithRandom = RANDOMS.getRedisTTLWithRandom(CONSTANTS._1_MONTH); + // Add data redis + book_admin_service.handleSetCacheRedis( + CONSTANTS.KEY_REDIS.ALL_BOOK, + result_book, + redisTTLWithRandom, + ); return res.status(200).json({ status: 200, diff --git a/backend-manager-student/src/user_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js b/backend-manager-student/src/user_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js index fd02ff5..9779768 100644 --- a/backend-manager-student/src/user_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js +++ b/backend-manager-student/src/user_api/v1/controllers/borrow_book.controllers/borrow_book.controller.js @@ -58,15 +58,15 @@ const BorrowBookController = { if (data_borrow_book.length > 0 && data_borrow_book[0].status !== CONSTANTS.STATUS_BORROW.DONE) { let result_borrow; switch (data_borrow_book[0].status) { - case CONSTANTS.STATUS_BORROW.PENDING: - result_borrow = 'Book already borrow !!'; - break; - case CONSTANTS.STATUS_BORROW.BORROWING: - result_borrow = 'Please return the book !!'; - break; - default: - result_borrow = 'Fail'; - break; + case CONSTANTS.STATUS_BORROW.PENDING: + result_borrow = 'Book already borrow !!'; + break; + case CONSTANTS.STATUS_BORROW.BORROWING: + result_borrow = 'Please return the book !!'; + break; + default: + result_borrow = 'Fail'; + break; } return res.status(400).json({ status: 400, diff --git a/backend-manager-student/src/user_api/v1/controllers/user.controllers/user.controller.js b/backend-manager-student/src/user_api/v1/controllers/user.controllers/user.controller.js index 1c6f993..6e78c7a 100644 --- a/backend-manager-student/src/user_api/v1/controllers/user.controllers/user.controller.js +++ b/backend-manager-student/src/user_api/v1/controllers/user.controllers/user.controller.js @@ -180,8 +180,8 @@ const userController = { sameSite: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, secure: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, domain: - CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT - ? req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] + CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? + req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] : CONSTANTS.HEADER_DOMAIN, maxAge: CONSTANTS._1_MONTH, }); @@ -420,8 +420,8 @@ const userController = { sameSite: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, secure: CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? true : false, domain: - CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT - ? req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] + CONFIGS.NODE_ENV === CONSTANTS.ENVIRONMENT_PRODUCT ? + req.headers[CONSTANTS.HEADER_HEADER_FORWARDED_HOST]?.split(':')[0] : CONSTANTS.HEADER_DOMAIN, maxAge: CONSTANTS._1_MONTH, }); @@ -1477,7 +1477,9 @@ const userController = { const { id } = req.auth_user; // Input body - const { name, avatar_uri, public_id_avatar, address, dob, gender } = req.body.input.user_update_profile_input; + const { + name, avatar_uri, public_id_avatar, address, dob, gender, + } = req.body.input.user_update_profile_input; // Check user_id if (!id) { diff --git a/backend-manager-student/src/user_api/v1/queue/book_user/book.user.js b/backend-manager-student/src/user_api/v1/queue/book_user/book.user.js new file mode 100644 index 0000000..0af7cae --- /dev/null +++ b/backend-manager-student/src/user_api/v1/queue/book_user/book.user.js @@ -0,0 +1,29 @@ +//! MIDDLAWRE +const { globalCache } = require('../../../../share/patterns/LRU_Strategy.patterns'); + +//! SHARE +const CONSTANTS = require('../../../../share/configs/constants'); + +const queueBookUser = { + /** + * @author Nguyễn Tiến Tài + * @created_at 15/03/2023 + * @description Queue delete key LRU + * @function deleteKeyLRU + * @return { Object } + */ + deleteKeyLRU: async (message_sub) => { + try { + // Check Key lru argothim + const check_key_lru_book_detail = globalCache.exitKeyCache(message_sub.result); + if (check_key_lru_book_detail === CONSTANTS.YES) { + // Add data cache lru argothim + globalCache.delCache(message_sub.result); + } + return false; + } catch (error) { + return true; + } + }, +}; +module.exports = queueBookUser; diff --git a/backend-manager-student/src/user_api/v1/queue/queue_redis.js b/backend-manager-student/src/user_api/v1/queue/queue_redis.js new file mode 100644 index 0000000..92955a2 --- /dev/null +++ b/backend-manager-student/src/user_api/v1/queue/queue_redis.js @@ -0,0 +1,51 @@ +//! LIBRARY +const IOREDIS = require('ioredis'); + +//! SERVICE +const book_user = require('./book_user/book.user'); + +//! SHARE +const CONSTANTS = require('../../../share/configs/constants'); +const CONFIGS = require('../../../share/configs/config'); + +//! DB +const REDIS_MASTER = new IOREDIS({ + port: CONFIGS.REDIS_PORT, + host: CONFIGS.REDIS_HOST, + user: CONFIGS.REDIS_USER, + password: CONFIGS.REDIS_PASSWORD, +}); + +/** + * @author Nguyễn Tiến Tài + * @created_at 15/03/2023 + * @description Setup Redis PubSub Server USER_API. + */ + +//! New Map Users +const userChannelHandlers = new Map(); +userChannelHandlers.set(CONSTANTS.DELETE_KEY_CACHE_LRU, book_user.deleteKeyLRU); + +//! Start Subscribe to user +REDIS_MASTER.on('ready', async () => { + try { + REDIS_MASTER.psubscribe(`${CONSTANTS.KEY_USER_EXIT_U}`); + + console.info(`Redis subscribed to all channels starting with ${CONSTANTS.KEY_USER_EXIT_U}`); + } catch (error) { + console.error('Failed to subscribe to Redis channels:', error); + } +}); + +//! Take queue Sub of Pub +REDIS_MASTER.on('pmessage', async (pattern, channel, message) => { + console.info(pattern, '::::::::pattern'); + const handler = userChannelHandlers.get(channel); + if (handler) { + try { + handler(JSON.parse(message)); + } catch (error) { + console.error(`Error processing Redis message on channel ${channel}:`, error); + } + } +}); diff --git a/backend-manager-student/src/user_api/v1/routes/index.router.js b/backend-manager-student/src/user_api/v1/routes/index.router.js index 567f4fd..be4c8d9 100644 --- a/backend-manager-student/src/user_api/v1/routes/index.router.js +++ b/backend-manager-student/src/user_api/v1/routes/index.router.js @@ -25,11 +25,10 @@ router.use('/api/v1/user/private', rate_limit_middleware, accessStudentMiddlewar */ router.use('/api/v1/user', rate_limit_middleware, router_general); -router.get('/check-status', (req, res) => - res.status(200).json({ - status: 'success', - message: 'OK', - }), +router.get('/check-status', (req, res) => res.status(200).json({ + status: 'success', + message: 'OK', +}), ); module.exports = router;