Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ Methods:
- <code title="get /v2/gen-ai/indexing_jobs">client.knowledgeBases.indexingJobs.<a href="./src/resources/knowledge-bases/indexing-jobs.ts">list</a>({ ...params }) -> IndexingJobListResponse</code>
- <code title="get /v2/gen-ai/indexing_jobs/{indexing_job_uuid}/data_sources">client.knowledgeBases.indexingJobs.<a href="./src/resources/knowledge-bases/indexing-jobs.ts">retrieveDataSources</a>(indexingJobUuid) -> IndexingJobRetrieveDataSourcesResponse</code>
- <code title="put /v2/gen-ai/indexing_jobs/{uuid}/cancel">client.knowledgeBases.indexingJobs.<a href="./src/resources/knowledge-bases/indexing-jobs.ts">updateCancel</a>(pathUuid, { ...params }) -> IndexingJobUpdateCancelResponse</code>
- <code title="polling helper">client.knowledgeBases.indexingJobs.<a href="./src/resources/knowledge-bases/indexing-jobs.ts">waitForCompletion</a>(uuid, { ...options }) -> IndexingJobRetrieveResponse</code>

# Models

Expand Down
69 changes: 69 additions & 0 deletions src/resources/knowledge-bases/indexing-jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as Shared from '../shared';
import { APIPromise } from '../../core/api-promise';
import { RequestOptions } from '../../internal/request-options';
import { path } from '../../internal/utils/path';
import { sleep } from '../../internal/utils/sleep';

export class IndexingJobs extends APIResource {
/**
Expand Down Expand Up @@ -113,6 +114,74 @@ export class IndexingJobs extends APIResource {
...options,
});
}

/**
* Polls for indexing job completion with configurable interval and timeout.
* Returns the final job state when completed, failed, or cancelled.
*
* @param uuid - The indexing job UUID to poll
* @param options - Polling configuration options
* @returns Promise that resolves with the final job state
*
* @example
* ```ts
* const job = await client.knowledgeBases.indexingJobs.waitForCompletion(
* '123e4567-e89b-12d3-a456-426614174000',
* { interval: 5000, timeout: 300000 }
* );
* console.log('Job completed with phase:', job.job?.phase);
* ```
*/
async waitForCompletion(
uuid: string,
options: {
/**
* Polling interval in milliseconds (default: 5000ms)
*/
interval?: number;
/**
* Maximum time to wait in milliseconds (default: 600000ms = 10 minutes)
*/
timeout?: number;
/**
* Request options to pass to each poll request
*/
requestOptions?: RequestOptions;
} = {},
): Promise<IndexingJobRetrieveResponse> {
const { interval = 5000, timeout = 600000, requestOptions } = options;
const startTime = Date.now();

while (true) {
const response = await this.retrieve(uuid, requestOptions);
const job = response.job;

if (!job) {
throw new Error('Job not found');
}

// Check if job is in a terminal state
if (job.phase === 'BATCH_JOB_PHASE_SUCCEEDED') {
return response;
}

if (job.phase === 'BATCH_JOB_PHASE_FAILED' || job.phase === 'BATCH_JOB_PHASE_ERROR') {
throw new Error(`Indexing job failed with phase: ${job.phase}`);
}

if (job.phase === 'BATCH_JOB_PHASE_CANCELLED') {
throw new Error('Indexing job was cancelled');
}

// Check timeout
if (Date.now() - startTime > timeout) {
throw new Error(`Indexing job polling timed out after ${timeout}ms`);
}

// Wait before next poll
await sleep(interval);
}
}
}

export interface APIIndexedDataSource {
Expand Down
58 changes: 58 additions & 0 deletions tests/api-resources/knowledge-bases/indexing-jobs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,62 @@ describe('resource indexingJobs', () => {
),
).rejects.toThrow(Gradient.NotFoundError);
});

describe('waitForCompletion', () => {
// Prism tests are disabled
test.skip('waits for job completion successfully', async () => {
const jobUuid = '123e4567-e89b-12d3-a456-426614174000';
const responsePromise = client.knowledgeBases.indexingJobs.waitForCompletion(jobUuid, {
interval: 100,
timeout: 1000,
});
const response = await responsePromise;
expect(response).toBeDefined();
expect(response.job).toBeDefined();
});

// Prism tests are disabled
test.skip('throws error when job fails', async () => {
const jobUuid = '123e4567-e89b-12d3-a456-426614174000';
await expect(
client.knowledgeBases.indexingJobs.waitForCompletion(jobUuid, {
interval: 100,
timeout: 1000,
}),
).rejects.toThrow();
});

// Prism tests are disabled
test.skip('throws error when job is cancelled', async () => {
const jobUuid = '123e4567-e89b-12d3-a456-426614174000';
await expect(
client.knowledgeBases.indexingJobs.waitForCompletion(jobUuid, {
interval: 100,
timeout: 1000,
}),
).rejects.toThrow('Indexing job was cancelled');
});

// Prism tests are disabled
test.skip('throws error when timeout is reached', async () => {
const jobUuid = '123e4567-e89b-12d3-a456-426614174000';
await expect(
client.knowledgeBases.indexingJobs.waitForCompletion(jobUuid, {
interval: 100,
timeout: 50, // Very short timeout
}),
).rejects.toThrow('Indexing job polling timed out');
});

// Prism tests are disabled
test.skip('throws error when job is not found', async () => {
const jobUuid = 'nonexistent-job-uuid';
await expect(
client.knowledgeBases.indexingJobs.waitForCompletion(jobUuid, {
interval: 100,
timeout: 1000,
}),
).rejects.toThrow('Job not found');
});
});
});