Skip to content

Commit b1a24ff

Browse files
radovanjorgicgithub-actions[bot]Atul-Butola
authored
Timeout handling documentation for Airdrop development (#283)
* Timeout handling documentation for Airdrop development * Fix last sentence * Update fern/docs/pages/airdrop/data-extraction.mdx Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Resolving comments --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Atul-Butola <[email protected]>
1 parent 010c127 commit b1a24ff

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

fern/docs/pages/airdrop/data-extraction.mdx

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ to retrieve all the items that should be synced with DevRev.
44
If the current run is an initial sync, this means all the items should be extracted.
55
Otherwise the extractor should retrieve all the items that were changed since the start of the last extraction.
66

7-
Each snap-in invocation runs in a separate runtime instance with a maximum execution time of 13 minutes.
7+
Each snap-in invocation runs in a separate runtime instance with a maximum execution time of 13 minutes.
88
After 10 minutes, the Airdrop platform sends a message to the snap-in to gracefully exit.
99

10-
If a large amount of data needs to be extracted, it might not all be extracted within this time frame.
11-
To handle such situations, the snap-in uses a state object.
10+
If a large amount of data needs to be extracted, it might not all be extracted within this time frame.
11+
To handle such situations, the snap-in uses a state object.
1212
This state object is shared across all invocations and keeps track of where the previous snap-in invocations ended in the extraction process.
1313

1414
## Triggering event
@@ -68,20 +68,20 @@ await adapter.emit(ExtractorEventType.ExtractionDataError, {
6868
### Extracting and storing the data
6969

7070
The SDK library includes a repository system for handling extracted items.
71-
Each item type, such as users, tasks, or issues, has its own repository.
72-
These are defined in the `repos` array as `itemType`.
71+
Each item type, such as users, tasks, or issues, has its own repository.
72+
These are defined in the `repos` array as `itemType`.
7373
The `itemType` name should match the `record_type` specified in the provided metadata.
7474

7575
```typescript
7676
const repos = [
7777
{
78-
itemType: 'todos',
78+
itemType: "todos",
7979
},
8080
{
81-
itemType: 'users',
81+
itemType: "users",
8282
},
8383
{
84-
itemType: 'attachments',
84+
itemType: "attachments",
8585
},
8686
];
8787
```
@@ -104,14 +104,14 @@ After initialization of repositories using `initializeRepos`,
104104
items should be then retrieved from the external system and stored in the correct repository by calling the `push` function.
105105

106106
```typescript
107-
await adapter.getRepo('users')?.push(items);
107+
await adapter.getRepo("users")?.push(items);
108108
```
109109

110110
Behind the scenes, the SDK library stores items pushed to the repository and uploads them in batches to the Airdrop platform.
111111

112112
### Data normalization
113113

114-
Extracted data must be normalized to fit the domain metadata defined in the `external-domain-metadata.json` file.
114+
Extracted data must be normalized to fit the domain metadata defined in the `external-domain-metadata.json` file.
115115
More details on this process are provided in the [Metadata extraction](/public/snapin-development/adaas/metadata-extraction) section.
116116

117117
Normalization rules:
@@ -130,15 +130,15 @@ Extracted items are automatically normalized when pushed to the `repo` if a norm
130130
```typescript
131131
const repos = [
132132
{
133-
itemType: 'todos',
133+
itemType: "todos",
134134
normalize: normalizeTodo,
135135
},
136136
{
137-
itemType: 'users',
137+
itemType: "users",
138138
normalize: normalizeUser,
139139
},
140140
{
141-
itemType: 'attachments',
141+
itemType: "attachments",
142142
normalize: normalizeAttachment,
143143
},
144144
];
@@ -161,15 +161,15 @@ All other fields are contained within the `data` attribute.
161161
"owner": "A3A",
162162
"rca": null,
163163
"severity": "fatal",
164-
"summary": "Lorem ipsum",
164+
"summary": "Lorem ipsum"
165165
}
166166
}
167167
```
168168

169169
If the item you are normalizing is a work item (a ticket, task, issue, or similar),
170-
it should also contain the `item_url_field` within the `data` attribute.
170+
it should also contain the `item_url_field` within the `data` attribute.
171171
This field should be assigned a URL that points to the item in the external system.
172-
This link is visible in the airdropped item in the DevRev app,
172+
This link is visible in the airdropped item in the DevRev app,
173173
helping users to easily locate the item in the external system.
174174

175175
```json {12}
@@ -205,13 +205,13 @@ echo '{}' | chef-cli fuzz-extracted -r issue -m external_domain_metadata.json >
205205

206206
## State handling
207207

208-
To enable information passing between invocations and runs, a limited amount of data can be saved as the snap-in `state`.
208+
To enable information passing between invocations and runs, a limited amount of data can be saved as the snap-in `state`.
209209
Snap-in `state` persists between phases in one sync run as well as between multiple sync runs.
210210

211211
You can access the `state` through SDK's `adapter` object.
212212

213213
```typescript
214-
adapter.state['users'].completed = true;
214+
adapter.state["users"].completed = true;
215215
```
216216

217217
A snap-in must consult its state to obtain information on when the last successful forward sync started.
@@ -243,3 +243,39 @@ await spawn<DummyExtractorState>({
243243
}
244244
});
245245
```
246+
247+
## Handling lambda timeout
248+
249+
When a worker thread is busy with other work and doesn't respond to exit messages from the main thread, it becomes blocked and can stall the sync process. To prevent this, the Airdrop SDK implements a two-tier timeout mechanism.
250+
251+
- The **soft timeout**, default of 10 minutes and configurable, sends an exit message to the worker thread, allowing it to gracefully shut down via the `onTimeout` function. How to configure this is shown in the example below.
252+
- If the worker does not respond within the **hard timeout**, default of 13 minutes, it is forcefully terminated.
253+
254+
This mechanism ensures that the snap-in does not hang indefinitely, and the system can recover cleanly in case of stuck or slow code execution.
255+
256+
The most common reason for missed soft timeouts is code that blocks the Node.js event loop. This can prevent the worker thread from processing the exit signal, leading to a hard timeout and forced termination.
257+
258+
To keep the worker thread responsive and ensure soft timeout handling works as intended:
259+
260+
- Avoid long synchronous loops or CPU-heavy operations that block the event loop.
261+
- Use `async/await` for I/O operations such as API calls or file reads.
262+
- Add periodic async breaks in tight loops using `Promise.resolve()`, `setTimeout()`, or `setImmediate()`.
263+
264+
You can find examples of correct timeout-safe code in the [timeout-handling test suite](https://github.com/devrev/adaas-sdk/tree/main/src/tests/timeout-handling).
265+
266+
To test how your snap-in responds to timeouts, you can configure a shorter timeout using the `spawn` function:
267+
268+
```typescript
269+
await spawn({
270+
event,
271+
initialState,
272+
workerPath,
273+
initialDomainMapping,
274+
options: {
275+
timeout: 5 * 1000, // 5 seconds
276+
isLocalDevelopment: true,
277+
},
278+
});
279+
```
280+
281+
This lets you simulate a soft timeout and validate that your worker shuts down.

0 commit comments

Comments
 (0)