인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

wdhgood123님의 프로필 이미지
wdhgood123

작성한 질문수

[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지

트랜잭션이 반복됩니다

작성

·

291

0

로그인 하는 동안 동일한 트랜잭션이 반복됩니다.

코드는 13강 강의한 내용에서 바뀐점은 없습니다.

돈이 계속 빠져나갑니다...

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

진짜 돈인줄 알고 깜짝 놀랐네요 ㅎㅎ 저거 경매 끝난 것 찾는 쿼리가 잘못된 것 같은데요??

wdhgood123님의 프로필 이미지
wdhgood123
질문자

module.exports = async () => {
    console.log('checkAuction');
    try {
    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1); // 어제 시간
    const targets = await Good.findAll({
      where: {
        SoldId: null,
        createdAt: { [Op.lte]: yesterday },
      },
    }); // 경매 시작 후 24시간이 지나도 낙찰을 받지 못한 상품
    targets.forEach(async (target) => {
      const success = await Auction.findOne({
        where: { GoodId: target.id },
        order: [['bid', 'DESC']],
      });
      await Good.update({ SoldId: success.UserId }, { where: { id: target.id } });
      await User.update({
        money: sequelize.literal(`money - ${success.bid}`),
      }, {
        where: { id: success.UserId },
      });
    }); // 낙찰자 지정
    const unsold = await Good.findAll({
        where: {
          SoldId: null,
          createdAt: { [Op.gt]: yesterday },
        },
    });
    unsold.forEach((target) => {
        const end = new Date(unsold.createdAt);
        end.setDate(end.getDate() + 1);
        schedule.scheduleJob(end, async () => {
            const t = await sequelize.transaction();
            try {
                const success = await Auction.findOne({
                where: { GoodId: target.id },
                order: [['bid', 'DESC']],
                transaction: t,
            });
            await Good.update({ SoldId: success.UserId }, { where: { id: target.id }, transaction: t });
            await User.update({
                money: sequelize.literal(`money - ${success.bid}`),
            }, {
                where: { id: success.UserId },
                transaction: t,
                });
            await t.commit();
            } catch (error) {
                await t.rollback();
            }
        })
    });
    } catch (error) {
        console.error(error);
    }
};

경매 끝난 것 찾는 쿼리가 정확이 어떤 것인가요? 

위 코드는 checkAuction.js 코드이며

router.post('/good', isLoggedIn, upload.single('img'), async (req, res, next) => {
  try {
    const { name, price } = req.body;
    const good = await Good.create({
      OwnerId: req.user.id,
      name,
      img: req.file.filename,
      price,
    });
    const end = new Date();
    end.setDate(end.getDate() + 1);
    schedule.scheduleJob(end, async () => {
      const t = await sequelize.transaction();
      try {
        const success = await Auction.findOne({
          where: { GoodId: good.id },
          order: [['bid', 'DESC']],
          transaction: t,
      });
        await Good.update({ SoldId: success.UserId }, { where: { id: good.id }, transaction: t });
        await User.update({
          money: sequelize.literal(`money - ${success.bid}`),
        }, {
          where: { id: success.UserId },
          transaction: t,
        });
        await t.commit();
      } catch (error) {
        await t.rollback();
      }
    })
    res.redirect('/');
  } catch (error) {
    console.error(error);
    next(error);
  }
});

상품을 가져오는 코드입니다.

강의 내용에서 따로 고친것은 없습니다.

 

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

코드 자체는 문제 없습니다. 저기 로그에서 SoldId, good.Id 같은 게 ?로 뜨는 데 이 부분을 console.log찍어서 직접 값을 확인하고, DB에서도 워크벤치로 제대로 들어있는지 확인이 필요합니다. SoldId가 null로 계속 유지되어서 자꾸 저 로직이 실행되는게 아닌가싶기도 하네요.

저 unsold 부분 직접 짜신 건가요? 제가 개정판에서 추가하려고 작성한 코드랑 거의 일치하네요. 저는 Good.update부분만 await good.setSold(success.UserId, { transaction: t })로 수정하긴 했습니다.

wdhgood123님의 프로필 이미지
wdhgood123
질문자

const unsold = await Good.findAll({
        where: {
          SoldId: null,
          createdAt: { [Op.gt]: yesterday },
        },
    });
    unsold.forEach((target) => {
        const end = new Date(unsold.createdAt);
        end.setDate(end.getDate() + 1);
        schedule.scheduleJob(end, async () => {
            const t = await sequelize.transaction();
            try {
                const success = await Auction.findOne({ // 경매를 내림차순으로 정렬한 것 중 첫번째(가장 큰 가격)
                where: { GoodId: target.id },
                order: [['bid', 'DESC']],
                transaction: t,
            });
            // await good.setSold(success.UserId)와 같다
            await Good.update({ SoldId: success.UserId }, { where: { id: target.id }, transaction: t });
            await User.update({
                money: sequelize.literal(`money - ${success.bid}`),
            }, {
                where: { id: success.UserId },
                transaction: t,
                });
        console.log(success.UserId);
        console.log(Good.id);
        console.log(unsold.createdAt);
        console.log(end);
            await t.commit();
            } catch (error) {
                await t.rollback();
            }
        })
    });
    } catch (error) {
        console.error(error);
  }

이 코드는 강의에 나와있는 코드입니다.

왜 이런 현상이 나온 것인지 파악했습니다.

서버를 재시작하면 위에 보시다시피 트랜잭션이 반복됩니다.

app.js의 checkAuction(); 호출로 실행되는것 같습니다.

그 중에서도 위에 올린 코드가 실행됩니다.

코드대로라면  스케쥴 모듈로 unsold.createAt에서 하루가 지난 Date에 실행되어야 하지만

콘솔로 찍어보니

이렇게 찍힙니다.

참고로 

시퀄라이즈에서 ?가 뜨는데 콘솔이나 워크벤쳐로 확인해보면 제대로 데이터가 저장됩니다.

왜 ?가 뜨는지는 잘 모르겠습니다

 

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

?는 시퀄라이즈가 의도적으로 데이터를 숨겨주는 겁니다. 보안사고 방지를 위해서요. createdAt이 제대로 시퀄라이즈 모델 같은 데도 들어있나요?

wdhgood123님의 프로필 이미지
wdhgood123
질문자

네. 생성될때에도 제대로 생성됩니다.

워크벤쳐에도 있습니다.

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

아 unsold.createdAt이 아니라 target.createdAt 하셔야합니다.

wdhgood123님의 프로필 이미지
wdhgood123

작성한 질문수

질문하기