트랜잭션과 멀티 데이터소스

단일 DAO

$userDAO->startTransaction();
try {
    $userDAO->insert($user);
    $userDAO->commit();
} catch (Throwable $e) {
    $userDAO->rollback();
    throw $e;
}

여러 DAO에 걸친 트랜잭션

DataSourceManager로 전역 트랜잭션을 열면, 이후 실행되는 모든 데이터소스가 자동으로 트랜잭션에 참여합니다.

use _Flexagon\Libs\DataSourceManager;

DataSourceManager::startTransaction();
try {
    $userDAO->insert($user);
    $orderDAO->insert($order);
    $pointDAO->update($point);
    DataSourceManager::commit();
} catch (Throwable $e) {
    DataSourceManager::rollback();
    throw $e;
}

커밋과 롤백은 커넥션 등록 순서의 역순으로 수행됩니다.

DAO에 데이터소스 지정

DATA_SOURCE_ID 상수를 재정의합니다.

class StatsDAO extends BaseMySqlDAO {
    const DATA_SOURCE_ID = 'analytics';   // _Global::$DATA_SOURCES['analytics']
    protected string $tableName = 'daily_stats';
}

접속 실패 처리

데이터 소스에 접속하지 못하면 DAO 생성자가 _Flexagon\DB\ConnectionException을 던집니다(기본값 _Global::$DB_CONNECT_FAILURE_FATAL = true). 잡지 않으면 요청이 500으로, CLI는 종료 코드 255로 끝납니다. 응답을 직접 정하려면 잡으세요.

// public/_entry.php
set_exception_handler(function (Throwable $e) {
    if ( $e instanceof \_Flexagon\DB\ConnectionException ) {
        http_response_code(503);
        TemplateLoader::show('maintenance');
        return;
    }
    throw $e;
});

예외 메시지에는 데이터 소스 이름만 들어갑니다($e->getDataSourceId(), _Global::$DATA_SOURCES의 키). 호스트와 계정이 담긴 드라이버 메시지는 에러 로그로 가고, 원본 PDOException은 getPrevious()로 꺼낼 수 있습니다. 운영에서는 display_errors를 꺼 두세요. 잡지 않은 예외를 화면에 출력하면 이전 예외까지 함께 나옵니다.

예외 대신 connect()가 false를 반환하게 하려면 $DB_CONNECT_FAILURE_FATAL = false로 두세요.