timeoutSeconds(최대 900초)로 제한됩니다. 해당 시간 안에 끝나지 않는 모든 작업(전체 재동기화, 레코드별 팬아웃, 속도 제한이 걸린 서드파티 API 등)은 더 작은 실행 단위로 나눠야 합니다.
enqueueJobs는 바로 그 일을 합니다. Twenty 워커에게 나중에 앱의 로직 함수 중 하나를 실행해 달라고 요청하며, 각 페이로드당 한 번씩 실행되고 각 실행은 자체 프로세스에서 자체 타임아웃 한도로 처리됩니다. 호출은 즉시 반환됩니다.
실행 대기열에 추가하기
twenty-sdk/logic-function에서 enqueueJobs를 가져와 실행할 로직 함수의 universalIdentifier를 지정하고, 대기열에 추가할 각 실행마다 하나의 페이로드를 전달하세요.
src/logic-functions/sync-all-contacts.ts
Logic function not found 오류와 함께 거부되며 아무것도 대기열에 추가되지 않습니다. 한 번의 호출로 최대 200개의 페이로드를 허용합니다.
enqueueJobs는 작업이 실행되었을 때가 아니라 작업이 수락되는 즉시 반환됩니다. 대상들의 결과를 반환하지는 않습니다. 결과를 다시 읽어와야 한다면, 각 대상이 생성한 내용을 키-값 스토어 또는 워크스페이스 레코드에 기록하도록 하세요.호출당 하나의 작업을 대기열에 추가하는 이전
enqueueJob 도우미는 더 이상 사용되지 않습니다. 대신 요소가 하나인 payloads 목록과 함께 enqueueJobs를 사용하세요.작업 옵션
옵션은 배치의 모든 실행에 적용됩니다.우선순위는 아직 설정할 수 없습니다. 대기열에 추가된 작업은 항상 가장 낮은 우선순위로 실행되므로, 플랫폼 작업이 애플리케이션 작업보다 뒤로 밀려 지연되는 일은 없습니다. 우선순위를 제어하는 기능은 곧 제공될 예정입니다.
일시적 실패 재시도하기
Twenty는 애플리케이션 코드의 모든 예외를 재시도하지 않습니다. 일반 오류가 throw되면 영구적 실패로 처리됩니다. 일시적 실패의 경우, 큐에 대기 중인 로직 함수는RetryableLogicFunctionError를 throw하여 최대 세 번의 재시도를 요청할 수 있습니다.
RetryableLogicFunctionError를 직접 throw하세요. 이를 확장하는 경우 name을 바꾸지 마세요. Twenty는 실행 런타임 전반에서 직렬화된 이름 RetryableLogicFunctionError를 인식합니다.
retryCount는 최초 실행 시 0이며, 애플리케이션 코드가 재시도를 요청할 때만 증가합니다. maxRetries는 최대 3이며, 큐에 대기 중인 작업의 전체 재시도 한도가 더 작으면 더 낮을 수 있습니다. 플랫폼 실패는 큐의 전체 안전 예산을 계속 소모하지만 retryCount를 증가시키지는 않습니다.
큐는 지수 백오프와 지터를 사용하여 재시도 시도를 지연합니다. 정확한 지연 시간은 의도적으로 보장되지 않으므로, 애플리케이션 코드는 정확한 시간에 재시도가 발생하는 것에 의존해서는 안 됩니다. maxRetries에 도달하면, 또 다른 RetryableLogicFunctionError는 추가 실행 없이 최종 애플리케이션 실패로 기록됩니다.
사용 예: 긴 동기화를 페이지 단위로 처리하기
전형적인 형태는, 다음 커서를 사용해 자기 자신을 다시 대기열에 추가하는 함수입니다. 각 실행은 자신의 타임아웃 안에서 한 페이지 분량의 작업만 처리하고, 더 이상 처리할 것이 없으면 이 체인은 멈춥니다.src/logic-functions/sync-contacts-page.ts
레코드별로 팬아웃하기
작업이 본질적으로 항목 단위일 때는, 단일 호출에서 항목마다 하나의 작업을 대기열에 추가하고 워커들이 인라인 루프를 도는 대신 병렬로 처리하도록 하세요.장시간 실행 작업을 위한 모범 사례
대부분의 장시간 작업은 두 가지 규칙으로 다룰 수 있습니다: 루프 대신 재귀를 사용하고, 실행마다 한정된 크기의 청크를 처리하세요. 한 번에 모든 것을 처리하려는 실행은 실패 패턴입니다. 타임아웃에 걸리고, 재시도가 발생하면 전체 작업을 다시 처음부터 시작합니다. 대신, 하나의 청크가timeoutSeconds 안에 여유 있게 끝나도록 크기를 잡고, 현재 위치를 저장한 뒤 다음 실행을 대기열에 추가하세요.
src/logic-functions/enrich-companies-batch.ts
- 청크 크기는 평균이 아니라 가장 느린 항목을 기준으로 정하세요.
CHUNK_SIZE × 최악의 항목 처리 시간은 여유를 두고timeoutSeconds안에 들어와야 합니다. 그렇지 않으면 실행이 중단될 때 청크의 끝부분이 유실됩니다. - 종료 조건을 명시적으로 만드세요. 가득 찬 청크가 반환되었을 때만 재귀적으로 호출하세요. “결과 없음”만을 기준으로 멈추는 체인은, 소스가 중간에 짧은 페이지를 한 번이라도 반환하면 영원히 계속될 수 있습니다.
- 다음 실행을 대기열에 추가하기 전에 진행 상태를 저장해서, 실패한 링크가 처음부터가 아니라 마지막으로 완료된 청크부터 다시 시작하도록 하세요.
- 각 청크는 멱등성을 유지하세요. 재시도 후에 하나의 청크를 다시 처리하더라도 중복 기록이 발생하지 않도록, 처리 중인 레코드나 외부 ID를 기준으로 쓰기를 수행해야 합니다.
- 거대한 한 번의 팬아웃보다 청크 단위 체인을 우선적으로 사용하세요. 작업이 호출 한도(rate limit)가 있는 서드파티에 도달하는 경우,
delayMs가 있는 체인은 스스로 속도를 조절하지만, 수천 개의 작업을 한 번에 대기열에 추가하면 모두 즉시 실행 가능 상태가 됩니다.