connect($redisHost, $redisPort); CLI::write('Worker started. Listening on naver:queue...'); while (true) { // 메인 큐 및 재시도 큐에서 데이터 꺼내기 (Blocking Pop, 5초 타임아웃) // LIFO (lPush/brPop) 사용 시: ['naver:queue:retry', 'naver:queue'] $item = $redis->brPop(['naver:queue'], 5); if ($item) { $payload = json_decode($item[1], true); $this->process($redis, $payload); // Redis 객체를 process에 전달 } } } private function process(\Redis $redis, $payload) { $articleNum = $payload['articleNumbr']; $requestType = $payload['reqeustType']; $retryCount = $payload['retry_count'] ?? 0; CLI::write("Processing {$requestType} for {$articleNum} (Attempt: " . ($retryCount + 1) . ")"); if (!in_array($requestType, ['REG', 'MOD'])) { CLI::write("Skipping non-verification request {$requestType} for {$articleNum}"); return; } // 1. 네이버 CP API 호출 $client = \Config\Services::curlrequest([ 'timeout' => 10, // ... (인증 헤더 설정 등 이전 답변의 보안 관련 항목 추가) ]); $url = "https://네이버CP/kiso/center/verification-article/{$articleNum}"; try { $response = $client->get($url); $statusCode = $response->getStatusCode(); if ($statusCode >= 200 && $statusCode < 300) { // 2. 성공 처리 CLI::write("✅ SUCCESS: {$requestType} for {$articleNum} (Status: {$statusCode})"); // 성공 시 DB에 결과 업데이트 등 후속 작업 진행 } else { // 3. API 실패 (4xx, 5xx 에러) $this->handleFailure($redis, $payload, $retryCount, "API returned Status: {$statusCode}"); } } catch (\Exception $e) { // 4. 네트워크/타임아웃 오류 $this->handleFailure($redis, $payload, $retryCount, "Network Error: " . $e->getMessage()); } } private function handleFailure(\Redis $redis, $payload, $retryCount, $reason) { $articleNum = $payload['articleNumbr']; if ($retryCount < self::MAX_RETRIES) { // 5. 재시도 로직: 재시도 횟수 증가 및 큐에 다시 푸시 $payload['retry_count'] = $retryCount + 1; // 지연된 재시도를 위해 Sorted Set (ZADD) 또는 별도의 큐 사용을 고려할 수 있으나, // 여기서는 단순성을 위해 즉시 재시도 큐에 넣고 sleep을 사용하는 방식을 가정합니다. // **주의: 실제 프로덕션 환경에서는 `Redis ZSET`을 사용하여 지연된 작업을 처리하는 것이 더 일반적입니다.** // 단순 재시도 큐 (ZSET을 사용하지 않는 경우) $redis->lPush('naver:queue:retry', json_encode($payload)); // CLI 환경에서 재시도 간 지연 시간을 강제 (Blocking pop을 쓰므로 실제 지연은 다음 worker 실행 시 발생) CLI::error("Attempt {$retryCount} FAILED for {$articleNum}. Reason: {$reason}. Retrying later."); } else { // 6. 최종 실패 처리: DLQ로 이동 $payload['fail_reason'] = $reason; $payload['fail_time'] = date('Y-m-d H:i:s'); $redis->lPush('naver:queue:dlq', json_encode($payload)); CLI::error("❌ CRITICAL FAIL: {$articleNum} moved to DLQ after " . self::MAX_RETRIES . " attempts."); } } }