ES /docs

[OpcOperation] Failed to get OPC API access token: {"errorCode"=>"ICS-11388", "status"=>"HTTP 409 Co

RCA: [OpcOperation] Failed to get OPC API access token — ICS-11388 409 Conflict

Error Log#

Datadog Logs

text
[OpcOperation] Failed to get OPC API access token: {"errorCode"=>"ICS-11388", "status"=>"HTTP 409 Conflict", "title"=>"Service Instance has been stopped and is unavailable at this time. Please contact your Service Instance administrator for additional information.", "type"=>"https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10"} - error: 409 Conflict

Impact#

  • Service: cupixworks-api
  • 발생 횟수: 5
  • 최초 발생: 2026-04-06T09:05:15.430Z
  • 최근 발생: 2026-04-06T09:12:36.400Z

Root Cause Summary#

Oracle Primavera Cloud(OPC) Service Instance가 중지(stopped) 상태여서 OPC API access token 요청이 HTTP 409 Conflict (에러코드 ICS-11388)로 거부되었습니다. 2단계 토큰 획득 과정 중 Step 1(OAuth2.0 인증)은 성공하지만, Step 2(OPC API access token 요청)에서 Oracle Integration Cloud 서버가 Service Instance가 중지되었다는 응답을 반환합니다. 이는 Cupix 코드의 버그가 아니라 외부 Oracle 서비스 인프라 문제입니다. 동일한 integration(6652)에서 에러 발생 약 23분 후(18:36 KST부터) 같은 요청이 정상 성공하는 것으로 확인되어, Oracle 측에서 Service Instance가 재시작된 것으로 판단됩니다.

Technical Analysis#

Code Path#

  • Entry point: IntegrationRepository#access_token (app/repositories/integration_repository.rb:76)
  • OPC provider 분기: app/repositories/integration_repository.rb:80-81opc_access_token 메서드로 위임
  • Step 1 (OAuth2.0): IntegrationRepository#opc_access_token (app/repositories/integration_repository.rb:339-345) — OpcOperation.get_access_token 호출
  • Step 2 (OPC API token): IntegrationRepository#opc_access_token (app/repositories/integration_repository.rb:365-368) — OpcOperation.get_opc_api_access_token 호출
  • Failure point: OpcOperation.get_opc_api_access_token (app/operations/opc_operation.rb:170) — RestClient.get 호출 시 409 응답 수신

Step 1 - OAuth2.0 인증 (성공):

ruby
# app/repositories/integration_repository.rb:339-345
oauth_token_response = OpcOperation.get_access_token(
  access_token_url: @model.opc['oic_oauth_token_url'],
  client_id: @model.opc['client_id'],
  client_secret: @model.opc['client_secret'],
  scope: @model.opc['scope']
)

이 단계는 정상적으로 OAuth2.0 access token을 반환합니다.

Step 2 - OPC API access token 요청 (실패):

ruby
# app/operations/opc_operation.rb:157-170
def self.get_opc_api_access_token(opc_api_url:, oauth_access_token:)
  headers = {
    authorization: "Bearer #{oauth_access_token}",
    accept: :json
  }
  # ...
  response = RestClient.get(opc_api_url, headers)  # 여기서 409 Conflict 발생

Oracle Integration Cloud 엔드포인트에 GET 요청 시 RestClient::Exception이 발생하며, 에러 응답 본문에 ICS-11388 코드와 "Service Instance has been stopped" 메시지가 포함됩니다.

에러 처리 및 로깅:

ruby
# app/operations/opc_operation.rb:197-222
rescue RestClient::Exception => e
  error_body = e.response&.body.to_s
  error_response = # ... JSON 파싱 ...
  Cupix::Logger.error(
    "[OpcOperation] Failed to get OPC API access token: #{error_response} - error: #{e.message}",
    class: self.name,
    function: __method__
  )
  raise Cupix::Errors::Parameter.new(
    code: ErrorCodes::INVALID_OPC_ACCESS_TOKEN_URL,
    reason: "OPC API access token request failed (Step 2): #{error_message}",
    message: e.message
  )

현재 코드는 409 응답(일시적 Service Instance 중지)을 Cupix::Errors::Parameter(INVALID_OPC_ACCESS_TOKEN_URL = OPB824)로 래핑합니다. 이는 URL이 잘못된 것이 아니라 서비스가 일시 중지된 상태이므로 에러 코드가 정확하지 않습니다.

Log Evidence#

사용한 Datadog 쿼리:

text
service:cupixworks-api status:error "OpcOperation" "ICS-11388"
text
service:cupixworks-api "integration(6652)"
text
service:cupixworks-api "OPC" "access token"

에러 발생 타임라인 (integration 6652):

시각 (KST) 레벨 메시지
18:05:15 info Step 1: OAuth2.0 authentication 시작
18:05:15 info Step 2: Requesting OPC API access token
18:05:15 error Failed to get OPC API access token: 409 Conflict
18:09:42 info Step 1: OAuth2.0 authentication 시작
18:09:42 info Step 2: Requesting OPC API access token
18:09:42 error Failed to get OPC API access token: 409 Conflict
18:10:17 info Step 1 시작
18:10:19 error 409 Conflict
18:11:24 info Step 1 시작
18:11:26 error 409 Conflict
18:12:36 info Step 1 시작
18:12:36 error 409 Conflict

복구 확인 — 에러 발생 후 정상 동작:

시각 (KST) 레벨 메시지
18:36:38 info Requesting OPC API access token
18:36:38 info Successfully retrieved OPC API access token
18:37:12 info Successfully retrieved OPC API access token
18:38:12 info Successfully retrieved OPC API access token
18:48:25 info Successfully obtained OPC API access token for integration(1635)
18:59:15 info Successfully obtained OPC API access token for integration(1635)

에러 발생 후 약 23분 뒤(18:36 KST)부터 정상 동작이 확인되어, Oracle Service Instance가 재시작된 것으로 판단됩니다.

추가 확인 — 같은 시간대 다른 에러:

에러 발생 1시간 전(08:00 UTC)에 동일한 OpcOperation.get_opc_api_access_token에서 500 Internal Server Error도 관찰되었습니다:

text
[OpcOperation] Failed to get OPC API access token: {"type"=>"http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1", "title"=>"Internal Server Error", ... "o:errorCode"=>"500", "o:errorPath"=>"<![CDATA[InboundJaxrsResponse{context=ClientResponse{method=POST, uri=https://primavera-us2.oraclecloud.com/primediscovery/apitoken/request?scope=http%3A%2F%2Fprimavera-us2.oraclecloud.com%2Fapi, status=500, reason=Server Error}}]]>"} - error: 500 Internal Server Error

이는 Oracle Primavera Cloud 서버 자체에서 500을 반환한 것으로, Service Instance 중지 이전에 이미 Oracle 인프라에 문제가 있었음을 시사합니다.

Fix Recommendation#

즉시 조치 (Critical)#

  • 조치 불필요 — 이 에러는 외부 Oracle Primavera Cloud Service Instance의 일시적 중지로 인한 것이며, Cupix 코드의 버그가 아닙니다. Oracle Service Instance가 이미 복구되어 정상 동작하고 있습니다.

단기 개선 (1주 이내)#

  • app/operations/opc_operation.rb:218-222: 409 Conflict 응답에 대해 INVALID_OPC_ACCESS_TOKEN_URL(OPB824) 에러 코드를 사용하는 대신, 외부 서비스 비가용(Service Unavailable) 상태를 나타내는 별도 에러 코드를 도입할 것을 권장합니다. 현재 코드는 모든 RestClient::Exception을 동일한 OPB824 코드로 처리하므로, URL 오류와 서비스 중지를 구분할 수 없습니다.
  • app/operations/opc_operation.rb:170: OPC API 요청에 retry 로직 추가를 고려할 수 있습니다. 409/500 같은 일시적 에러에 대해 1-2회 재시도(exponential backoff)를 적용하면 일시적 Oracle 서비스 장애 시 자동 복구될 수 있습니다.

장기 개선 (재발 방지)#

  • OPC Service Instance 상태를 모니터링하는 health check 메커니즘 도입을 고려합니다. Oracle Integration Cloud의 상태를 주기적으로 확인하여, Service Instance가 중지된 경우 사전에 알림을 받을 수 있도록 합니다.
  • Integration 모델에 마지막 에러 상태와 시간을 기록하여, 동일 에러가 반복되면 자동으로 integration 상태를 degraded로 전환하고 사용자에게 알림을 보내는 로직을 추가합니다.

Monitoring#

  • OPC API access token 요청 실패율 모니터링:
text
service:cupixworks-api status:error "OpcOperation" "Failed to get OPC API access token"
  • 특정 에러 코드별 분류:
text
service:cupixworks-api status:error "OpcOperation" "ICS-11388"
  • Integration별 실패 추적:
text
service:cupixworks-api status:error "Integration" "Failed to get OPC API access token" "integration(6652)"

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial
  • 이 에러는 외부 Oracle 서비스의 일시적 장애로 인한 것이며, 이미 자동 복구되었습니다. 사용자 영향은 약 30분간 OPC 연동 기능 사용 불가에 한정됩니다. integration(6652) 한 건에만 영향이 있었으며, 같은 시간대 다른 integration(1635 등)은 정상 동작하고 있었습니다.