본문으로 건너뛰기

소개

Queuety은 빠른 작업 큐, 내구성 있는 워크플로우 엔진 및 내구성 있는 상태 머신 런타임을 제공하는 WordPress 플러그인입니다. 워커는 MySQL에서 직접 작업을 가져와 장시간 실행되는 WP-CLI 프로세스 안에서 처리합니다. WordPress 및 WP-CLI을 로드하는 PHP 런타임에는 mysqli 또는 pdo_mysql이 필요합니다.

Queuety을 사용하는 이유는 무엇인가요?

WordPress에는 실제 백그라운드 작업 시스템이 없습니다. wp_cron은 페이지 방문 시에만 실행됩니다. Action Scheduler의 기본 실행기는 WP-Cron 및 루프백 HTTP 요청을 이용하며, 각 요청은 최대 30초 동안 배치를 처리합니다. 60초가 걸리는 LLM API 호출은 PHP의 30초 시간 초과로 종료됩니다. 충돌 후에도 살아남아 중단 지점에서 재개하는 다단계 프로세스를 실행할 방법이 없습니다.

Queuety은 세 가지 기본 요소로 이 문제를 해결합니다:

  1. 작업은 실행 후 잊어도 되는 백그라운드 작업에 사용합니다.
  2. 워크플로우는 상태를 유지하는 내구성 있는 다단계 프로세스에 사용합니다.
  3. 상태 머신은 오래 지속되는 이벤트 기반 수명 주기 상태를 모델링합니다.

빠른 예제

최신 API을 사용해 작업을 디스패치하세요:

PHP
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

readonly class SendEmailJob implements Job {
    use Dispatchable;

    public function __construct(
        public string $to,
        public string $subject,
        public string $body,
    ) {}

    public function handle(): void {
        wp_mail( $this->to, $this->subject, $this->body );
    }
}

SendEmailJob::dispatch( 'user@example.com', 'Welcome', 'Hello from Queuety!' );

또는 기존 핸들러 이름 방식을 사용하세요:

PHP
use Queuety\Queuety;

Queuety::dispatch( 'send_email', [ 'to' => 'user@example.com' ] );

내구성 있는 워크플로우를 실행하세요:

PHP
Queuety::workflow( 'generate_report' )
    ->then( FetchDataHandler::class )
    ->then( CallLLMHandler::class )
    ->then( FormatOutputHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );

상태 머신으로 오래 지속되는 세션을 모델링하세요:

PHP
use Queuety\Enums\StateMachineStatus;

Queuety::machine( 'agent_session' )
    ->state( 'awaiting_user' )
    ->on( 'user_message', 'planning' )
    ->state( 'planning' )
    ->action( PlanSessionAction::class )
    ->on( 'planned', 'completed' )
    ->state( 'completed', StateMachineStatus::Completed )
    ->dispatch( [ 'thread_id' => 42 ] );

워커를 시작하세요:

셸
wp queuety work

에이전트 스타일 시스템을 구축한다면 에이전트 오케스트레이션부터 시작하세요. 플래너/실행기 흐름, 사람의 검토 단계, 워크플로우 간 대기가 어떻게 함께 작동하는지 설명합니다.

시스템이 이벤트 기반이고 오래 지속된다면 워크플로우와 함께 상태 머신부터 살펴보세요.

엔드투엔드 통합 예제가 필요하면 예제를 확인하세요. 여기에는 제공자 전환, 스트리밍, 메모리 기반 검토 반복 및 종속 워크플로우를 위한 Neuron 기반 패턴이 포함되어 있습니다.

WordPress 같은 save_post 도메인 이벤트에서 워크플로우를 시작하려면 액션 트리거를 확인하세요.

DB 기반 런타임을 WordPress 외부에서 사용하려면 독립 실행형 사용을 확인하세요.

주요 차별점

  • 빠른 실행. 워커는 직접 MySQL 큐에 액세스하므로 WordPress의 백그라운드 작업을 느리게 만드는 요청별 cron 패턴을 피합니다.
  • 내구성 있는 워크플로우. 지속 상태를 사용하는 다단계 프로세스는 PHP 시간 초과, 충돌 및 재시도에도 유지됩니다. 각 단계 경계는 원자적 MySQL 트랜잭션입니다.
  • 명시적 상태 머신. 이름이 지정된 상태, 가드가 있는 전환, 큐에 등록되는 상태 진입 작업, 내구성 있는 이벤트 타임라인으로 채팅 세션, 승인 및 기타 장기 수명 주기를 모델링합니다.
  • 최신 디스패치 API. Dispatchable 트레이트, 페이로드 역할을 하는 타입 지정 생성자 속성, 클래스에 선언된 $tries/$timeout/$backoff을 사용하는 독립형 작업 클래스입니다. readonly 클래스에서는 이러한 속성에 기본값을 지정할 수 없으므로 readonly 승격 생성자 속성을 사용하는 일반 클래스에 선언하세요.
  • 미들웨어 파이프라인. 속도 제한, 예외 스로틀링, 고유 작업 및 사용자 지정 로직을 위한 양파형 미들웨어입니다. 작업별 middleware() 메서드로 선언합니다.
  • 스트리밍 단계. StreamingStep 인터페이스는 청크를 생성해 데이터베이스에 즉시 저장합니다. 재시도 시 이전에 저장된 청크가 전달되므로 스트림을 중단된 지점부터 재개할 수 있습니다. LLM 응답 및 대용량 다운로드에 적합합니다.
  • 플러그형 캐시 계층. CacheFactory은 APCu를 자동 감지하고, 사용할 수 없으면 메모리 내 캐시로 대체합니다. 사용자 지정 백엔드는 Contracts\Cache를 구현합니다. 속도 제한 조회 및 큐 상태에 내부적으로 사용됩니다.
  • 배칭 및 체이닝. then/catch/finally 콜백과 진행률 추적을 사용해 작업 그룹을 디스패치하거나, 앞 작업이 완료되어야 다음 작업이 진행되는 순차 작업 체인을 구성합니다.
  • 내구성 있는 지연 및 대기. delay()은 프로세스가 재시작되어도 유지되는 지연을 추가합니다. wait_for_signal(), wait_for_signals(), wait_for_approval(), wait_for_input() 및 wait_for_workflow()을 사용하면 PHP을 계속 실행하지 않고도 외부 이벤트나 다른 워크플로우를 기다리도록 워크플로우를 일시 중지할 수 있습니다.
  • 동적 for-each. for_each()는 워크플로우 상태에서 런타임에 검색된 분기 작업을 확장하고 전체 성공, 첫 성공 및 정족수 완료 모드를 지원합니다.
  • 비동기 워크플로우 핸드오프. start_workflows()은 런타임에 검색된 항목을 나중에 기다릴 수 있는 독립적인 최상위 워크플로우로 전환합니다.
  • WordPress 액션 트리거. on_action()은 코어 또는 플러그인 액션 훅을 게이팅 및 멱등성을 갖춘 내구성 있는 워크플로우 디스패치에 연결합니다.
  • 내구성 있는 아티팩트. 이름이 지정된 워크플로우 출력을 기본 상태 저장소 외부에 저장하고 상태, CLI 검사, 내보내기 및 재생 과정에서 유지합니다.
  • 워크플로우 가드레일. version(), 결정적 정의 해시, 멱등성 디스패치 키 및 워크플로우 예산을 통해 에이전트 스타일 실행을 더 쉽게 검사하고 중복 실행이나 제어되지 않는 실행을 방지합니다.
  • 리소스 관리. 동시성 그룹, 비용 단위, 워크플로우 예산 및 워커 승인으로 비용이 큰 에이전트 스타일 작업을 정해진 한도 안에서 실행하도록 합니다.
  • 단계 보상. compensate_with() 및 compensate_on_failure()는 워크플로우가 취소되거나 실패할 때 완료된 단계를 롤백하는 훅을 제공합니다.
  • 하트비트. 장시간 실행되는 단계는 하트비트를 전송해 오래된 작업 복구 시스템이 활성 작업을 회수하지 못하게 합니다.
  • 워크플로우 추적. 모든 단계 전환은 입력, 출력, 전후 상태, 컨텍스트, 아티팩트, 청크, 오류와 함께 기록되며 workflow_state_at()을 사용한 시간 여행 디버깅도 지원합니다.
  • 병렬 단계. 여러 단계를 동시에 실행하고 모두 완료될 때까지 기다린 후 다음 단계로 진행합니다.
  • 조건부 분기. _next_step을 사용해 이전 상태에 따라 이름이 지정된 단계로 건너뜁니다.
  • 워크플로우 실행. 결과를 부모에게 반환하는 자식 워크플로우를 시작합니다.
  • 우선순위 큐. 타입 안전 PHP 열거형을 통해 낮음, 보통, 높음, 긴급의 네 가지 우선순위를 지원합니다.
  • 다중 큐 워커. 하나의 워커에서 엄격한 우선순위 순서로 여러 큐를 처리합니다.
  • 속도 제한. 슬라이딩 윈도우 방식으로 핸들러별 실행 횟수를 제한합니다.
  • 반복 작업. 간격 기반 및 cron 기반 예약과 구성 가능한 중복 실행 정책(허용, 건너뛰기, 버퍼링)을 지원합니다.
  • 워크플로우 취소. 실행 중인 워크플로우를 취소하고 등록된 정리 핸들러를 실행합니다.
  • 상태 정리. 오래된 단계 출력을 자동으로 제거해 대형 워크플로우 상태를 관리하기 쉽게 유지합니다.
  • 워커 동시성. --workers=N는 여러 프로세스를 분기하고 충돌 시 자동으로 재시작합니다.
  • 완전한 관측성. 데이터베이스 로깅, 핸들러별 메트릭 및 이벤트 웹훅을 제공합니다.
  • 테스트 유틸리티. QueueFake는 단위 테스트에서 단언할 수 있도록 디스패치된 작업과 배치를 기록합니다.
  • PHP 속성. #[QueuetyHandler('name')]을 사용해 설정 없이 핸들러를 등록합니다.

작동 방식

워커는 오래 실행되는 WP-CLI 프로세스 안에서 실행되며 MySQL에서 직접 작업을 가져옵니다. 큐 행, 워크플로우 상태, 로그, 배치, 신호 및 스트리밍 청크는 모두 MySQL에 저장되므로 워커가 재시작되어도 오케스트레이션 상태가 사라지지 않습니다.

워크플로우는 장시간 실행되는 작업을 단계로 나눕니다. 각 단계는 출력을 데이터베이스의 공유 상태 저장소에 유지합니다. PHP이 단계 실행 중 종료되면 워커는 이전 상태를 모두 보존한 채 해당 단계를 재시도합니다. 단계 경계는 하나의 MySQL 트랜잭션입니다. 상태 업데이트, 작업 완료 및 다음 단계 큐 등록이 모두 원자적으로 수행됩니다.

코드
Workflow: generate_report (3 steps)

Step 0: fetch_data     -> state: {user_data: {...}}
Step 1: call_llm       -> PHP dies -> retry -> state: {user_data: {...}, llm_response: "..."}
Step 2: format_output  -> state: {user_data: {...}, llm_response: "...", report_url: "/reports/42.pdf"}

Workflow: completed

요구 사항

  • PHP 8.2 이상
  • WordPress 6.4 이상
  • MySQL 8.0+ 또는 MariaDB 10.6+ (워커가 SELECT ... FOR UPDATE SKIP LOCKED를 사용해 작업을 가져오기 때문)
  • WordPress 및 WP-CLI을 로드하는 PHP 런타임의 mysqli 또는 pdo_mysql
  • wp queuety work로 전용 워커를 실행하기 위한 WP-CLI
  • 워커 풀을 위한 pcntl 및 posix PHP 확장(--workers, --min-workers, --max-workers)

설치는 시작하기를 참고하세요.