Node.js Core & Model : Where Sequelize Transaction Object Made

Heechul Yoon·2020년 7월 22일
0

LOG

목록 보기
57/62

in MSA node.js architecture, we divide the project into modules which has it's role in the project.

there is three main modules playing an important role at a project.

route for routing
core for business logic
model for communication with database.

this posting is mainly about where we make the sequelize transaction for the database update and ideal role of model and core at one project.

Transaction

then, what is transaction?
let's say we are about to update the user profile information such as name, email, sns_url, sns_visibility...

name,email are at [user] table and sns_url, sns_visibility are at [user_sns] table. and both tables are in one to many relationship as one user could have many sns information like facebook, instagram.

once you update name and sns_url, you need to update two different table. but what if the client send the those updating request and get an error during updating sns_url in [user_sns] table with the completion of name update from the [user] table. this is going to give distrust about the service to users.

  • update name from [user]
  • update sns_url from [user_sns]

those two operation have to be done in one scope, otherwise it have to be back to the initial stage of the operation. at this point, we can create and attach the transaction to the each scope and commit the transaction once every operations are guaranteed to have been done by the transaction.

Core & Model

then how we define the range of core and model?
what role should be assigned to each module?

let us get down to the common understanding

  • core : section in charge of business logic for an API
  • model : section in charge of database communication
async getMemberList(memberFilter) {
    try {
      /**
       * Get new members joined latest month
       */

[1]   if (memberFilter.is_new === 1) {
        const nowYearMonth = this.getNow().slice(0, 7)
        const newMemberList = await BranchMemberView.findAll({
          where: {
            type: searchIdUseValue("member_type", "regular member"),
            branch_id: memberFilter.branchId,
            created_at: {
              [this.Op.like]: `%${nowYearMonth}%`
            }
          },
          attributes: ["uuid", "profile_image", "is_visible_profile_image", "type", "nickname", "interest", "is_visible_interest", "introduction", "is_visible_introduction", "instagram_visible", "facebook_visible", "twitter_visible", "tiktok_visible"],
          order: [["created_at", "ASC"]],
          offset: memberFilter.offset,
          limit: memberFilter.limit,
          raw: true
        })
[2]     if (!newMemberList.length) {
          logger.verbose("Failed to get new member list", this.getMemberList.name, [memberFilter])

          return false
        }
        logger.verbose("Successfully retrieve new member list", this.getMemberList.name, [memberFilter])

        return newMemberList
      }


      /**
       * Get existing members
       */

      const memberList = await BranchMemberView.findAll({
        where: {
          [this.Op.or]: [{ type: searchIdUseValue("member_type", "regular member") }, { type: searchIdUseValue("member_type", "associate member") }],
          branch_id: memberFilter.branchId
        },
        attributes: ["uuid", "profile_image", "is_visible_profile_image", "nickname", "type"],
        order: [["created_at", "ASC"]],
        offset: memberFilter.offset,
        limit: memberFilter.limit,
        raw: true
      })
[3]   if (!memberList.length) {
        logger.verbose("Failed to get member list", this.getMemberList.name, [memberFilter])

        return false
      }
      logger.verbose("Successfully retrieve member list", this.getMemberList.name, [memberFilter])

      return memberList
    } catch (err) {
      logger.verboseError(`Failed to read database with error: ${err}`, this.getMemberList.name, [memberFilter])
      throw new Error(`[EA501] MemberModel.getMemberList with error: ${err}`)
    }
  }

let us see through the bad example of model
this is the model of a feature to get user list. If query param is_new is received, model logic get to search new user at the model.

and if not, logic skip the "if" block.

  1. It seems model have more role than it supposed to have ,in which have business logic that is supposed to be operated at the core level([2], [3])

  2. There is two main logic in one function separated by if which can be apart as two function get_new_members and get_members

In summary, core is for business logic such as data reformation, catch an error and model is no more than CRUD on database. if you are in need to filter or reform the data from database, the operation should be conducted at the core level. so transaction should be made and operated at the core level as well.

There is no strict rule when you code. However, when in comes to cooperation at the work place, the rule matters due to the communication cost.

profile
Quit talking, Begin doing

0개의 댓글