Graphql 장점
1.여러 개의 endpoint가 단일화 → POST /graphql
2.한번에 여러 API요청 가능
3.원하는 결과만 받을 수 있다.
graphql의 내부적인 에러는 항상 200이다.
다만, type에러는 graphql이 잡아준다.
.create( ) : DB로 저장되는 것이 아니라, 해당 데이터를 가진 객체가 만들어 집니다.
.save( ) : save를 통해 만들어진 객체가 DB에 저장됩니다.
.update( ) : 얼만큼 수정이 이루어졌는가의 대한 결과가 return 되며, DB에 저장도 됩니다.
Postman에서 query날리기
{
"query": "query { fetchBoards { writer, title, contents} }"
}
트랜잭션 - commit과 rollback
작업의 단위
성공!! 1. PointTransaction 테이블에 충전했다고 1줄 작성한다.
실패!! 2. User 테이블에서 철수 데이터를 가져온다.
3. 기존 500원에 충전 3000원을 더한 3500원으로 업데이트 한다.
1, 2, 3을 하나로 묶음 → 트랜잭션
서로 다른 Transaction을 부분적으로 처리합니다.
모든 Transaction(1, 2, 3)이 정상적으로 완료되면 Commit 합니다.
만약 Transaction 중 하나라도 비정상적으로 처리되면 rollback을 수행합니다.
=========================================================================
ACID
Atomicity(원자성) : 모두 성공할 거 아니면 다 실패하게 해줘!(데이터 오염은 싫어)
Consistency(일관성) : 동일한 쿼리는 조회할 때 마다 동일해야 한다.
Isolation(격리성): 철수 유저꺼를 처리하는 동안 영희는 기다린다.
Durability(지속성): 한 번 성공했으면 장애가 발생해도 살아있어야 된다.
==========================================================================
try { 시도하세요 }
catch{ 에러가 나면 이쪽으로 }
finally { 에러와 무관하게 항상 실행 }
queryRunner만이 Transaction과 관련이 있다.
queryRunner를 통해서 저장되어야 commit과 rollback이 가능함
===========================================
sql명령어
show variables;
set global max_connections = 155;
show status;
show processlist;
kill 48;
// pointTransaction.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Connection, Repository } from 'typeorm';
import { User } from '../users/entities/user.entity';
import {
PointTransaction,
POINT_TRANSACTION_STATUS_ENUM,
} from './entities/pointTransaction.entity';
@Injectable()
export class PointTransactionService {
constructor(
@InjectRepository(PointTransaction)
private readonly pointTransactionRepository: Repository<PointTransaction>,
@InjectRepository(User)
private readonly userRepository: Repository<User>,
private readonly connection: Connection,
) {}
async create({ impUid, amount, currentUser }) {
const queryRunner = await this.connection.createQueryRunner();
await queryRunner.connect();
// ============== transaction 시작!! ==============
await queryRunner.startTransaction();
// ===============================================
try {
// 1. pointTransaction 테이블에 거래기록 1줄 생성
const pointTransaction = this.pointTransactionRepository.create({
impUid: impUid,
amount: amount,
user: currentUser,
status: POINT_TRANSACTION_STATUS_ENUM.PAYMENT,
});
// await this.pointTransactionRepository.save(pointTransaction);
await queryRunner.manager.save(pointTransaction);
throw new Error('강제로 에러 발생!!!');
// 2. 유저의 돈 찾아오기
const user = await this.userRepository.findOne({ id: currentUser.id });
//3. 유저의 돈 업데이트
// await this.userRepository.update(
// { id: user.id },
// { point: user.point + amount },
// );
const updatedUser = await this.userRepository.create({
...user,
point: user.point + amount,
});
await queryRunner.manager.save(updatedUser);
// ============== commit 성공 확정!!! ==============
await queryRunner.commitTransaction();
// ===============================================
// 4. 최종결과 프론트엔드에 돌려주기
return pointTransaction;
} catch (error) {
// ============== rollback 되돌리기!!! ==============
await queryRunner.rollbackTransaction();
// ===============================================
} finally {
// ============== 연결 해제!!! ==============
await queryRunner.release(); //연결 해제를 하지 않는 경우 connection이 누적되어 최종적으로는 서버 다운
// ========================================
}
}
}
'고농축 백엔드' 카테고리의 다른 글
고농축 벡엔드 14 - 구글 인증 후 구글에서 받은 데이터를 DB에 저장 (0) | 2023.02.16 |
---|---|
고농축 벡엔드 13 - Google 로그인 (0) | 2023.02.14 |
고농축 벡엔드 12 - RefreshToken + Cookie (0) | 2023.02.13 |
고농축 벡엔드 11 - AccessToken과 Header의 Authorization// fetchUser() (0) | 2023.02.13 |
고농축 백엔드 docker-bind★★ (0) | 2023.01.31 |