Render Tutorials
Stock research: from flaky to reliable

Register searchOne with retries

⏱ 8 min

Wrap searchOne in task(). Keep maybeFail, getExa, and the Exa call body unchanged: the workshop keeps the same transient error simulation for search. Retry logic handles most transient failures.

Import task

At the top of tasks/src/search.ts:

tasks/src/search.ts
import { task } from '@renderinc/sdk/workflows'

Replace the export

Before
- export async function searchOne(
- _topic: string,
- spec: SearchSpec,
- index: number,
 
 
 
 
 
 
 
 
 
 
 
): Promise<SearchResult> {
- maybeFail(spec.query)
- // ... Exa call ...
- }
 
 
 
 
After
 
 
 
 
+ export const searchOne = task(
+ {
+ name: 'searchOne',
+ plan: 'starter',
+ timeoutSeconds: 120,
+ retry: { maxRetries: 3, waitDurationMs: 1000, backoffScaling: 1.5 },
+ },
+ async function searchOne(
+ _topic: string,
+ spec: SearchSpec,
+ index: number,
): Promise<SearchResult> {
 
 
 
+ maybeFail(spec.query)
+ // ... Exa call unchanged ...
+ },
+ )
FieldWhy
name: 'searchOne'Becomes {service-slug}/searchOne in startTask
plan: 'starter'Light Exa call
timeoutSeconds: 120Room for Exa latency
retry.maxRetries: 3Up to four attempts when maybeFail throws

Close the task() call at the end of the function with }, ).

Build

Terminal
$cd tasks && npm run build
Build succeeded

What you learned

  • searchOne becomes export const searchOne = task({ ... }, async function ...)
  • maybeFail stays unchanged so retries have something to recover from
  • Build tasks/ before moving on