TCC란 Try-Confirm/Cancel로, 분산된 REST 시스템들 간의 트랜잭션을 HTTP와 REST 원칙으로 접근하여 해결하는 방법이다.
현재, 필자는 수강편람과 학생의 수강기록에 따른 시간표 생성 시스템을 구축하는 중이다. 이 시스템은 spring boot Rest api 서버를 메인으로 flask 바탕으로한 crawling서버가 있다.
(Crawling은 유저가 최초 회원가입을 할 때, 혹은 새로운 학기에 처음 로그인할 때만 진행한다.)

기존 서비스와 달리 이번에는 1인당 1번만 시간표를 생성할 수 있다고 하자.(추가로 할려면 돈을,,,,)
진행 순서는 이렇다.

시간표를 생성할 때, 2단계 혹은 3단계 중 하나라도 실패할 경우 의도한 데이터를 생성하여 TimeTableDB에 넣을 수 없다.
이때, 각 서비스 호출에 대해 실패할 경우, 롤백하지 않으면 일관성이 깨지고 만다. 즉, 시간표 생성 요청에 대해 트랜잭션 처리가 보장되어야 한다.
TCC는 트랜잭션 처리를 관계형데이터베이스와 비슷하게 처리한다.

RestApi 호출 한 번에 끝이 아니라, try로 위 단계를 한 번 돌고 5단계까지 진행한 후 2단계부터 confirm을 다시 요청한다.
Try 중 실패가 발생하면 Confirm 대신 cancel을 쏜다.
makeTimeTableService는 makeTable 메서드로 시간표를 생성한다. 이곳이 트랜잭션 포인트다.
TccRestAdapter는 TCC Rest 커뮤니케이션을 담당한다.
TccRestAdapter로 수강편람과 학생의 학점을 체크요청을 try하고 오류가 없으면 confirm을 요청한다.
@Service
public class MakeTimeTableServiceImpl implements TimeTableService {
private TccRestAdapter tccRestAdapter;
@Autowired
public void setTccRestAdapter(TccRestAdapter tccRestAdapter) {
this.tccRestAdapter = tccRestAdapter;
}
@Override
public void makeTable(final Order order) {
// 수강편람 체크(Try)
ParticipantLink conditionParticipantLink = checkConditon(order);
// 학생 학점 체크(Try)
ParticipantLink creditParticipantLink = checkCredit(order);
// ...
// 확정(Confirm)
tccRestAdapter.confirmAll(conditionParticipantLink.getUri(), creditParticipantLink.getUri());
}
private ParticipantLink checkConditon(final Order order) {
final String requestURL = "http://localhost:8081/api/v1/condtion";
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("adjustmentType", "REDUCE");
requestBody.put("userId", order.getUserId());
requestBody.put("condition", order.getCondition());
return tccRestAdapter.doTry(requestURL, requestBody);
}
private ParticipantLink checkCredit(final Order order) {
final String requestURL = "http://localhost:8082/api/v1/credit";
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("userId", order.getUserId());
requestBody.put("credit", order.getCredit());
return tccRestAdapter.doTry(requestURL, requestBody);
}
}