Skip to content

Commit d488eef

Browse files
author
Abel Milash
committed
Add concurrent chunk dispatch (max_workers) for bulk record operations
1 parent 10b9765 commit d488eef

10 files changed

Lines changed: 593 additions & 92 deletions

File tree

.claude/skills/dataverse-sdk-use/SKILL.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Use the PowerPlatform Dataverse Client Python SDK to interact with Microsoft Dat
2525
- `client.batch` -- batch multiple operations into a single HTTP request
2626

2727
### Bulk Operations
28-
The SDK supports Dataverse's native bulk operations: Pass lists to `create()`, `update()`, or `upsert()` for automatic bulk processing; for `delete()`, set `use_bulk_delete=True`. Lists exceeding 1,000 records are automatically split into sequential 1,000-record chunks — no manual pre-splitting needed. Operations across chunks are **not atomic**: a failure mid-way may leave earlier chunks applied. Callers that require atomicity should limit their input to ≤ 1,000 records.
28+
The SDK supports Dataverse's native bulk operations: Pass lists to `create()`, `update()`, or `upsert()` for automatic bulk processing; for `delete()`, set `use_bulk_delete=True`. Lists exceeding 1,000 records are automatically split into 1,000-record chunks — no manual pre-splitting needed. By default chunks are dispatched sequentially; pass `max_workers=N` (recommended: 3–4) to dispatch chunks concurrently via threads. Operations across chunks are **not atomic**: a failure mid-way may leave earlier chunks applied. Callers that require atomicity should limit their input to ≤ 1,000 records.
2929

3030
### Paging
3131
- Control page size with `page_size` parameter
@@ -465,11 +465,12 @@ except ValidationError as e:
465465
### Performance Optimization
466466

467467
1. **Use bulk operations** - Pass lists to create/update/delete for automatic optimization
468-
2. **Specify select fields** - Limit returned columns to reduce payload size
469-
3. **Control page size** - Use `top` and `page_size` parameters appropriately
470-
4. **Reuse client instances** - Don't create new clients for each operation
471-
5. **Use production credentials** - ClientSecretCredential or CertificateCredential for unattended operations
472-
6. **Error handling** - Implement retry logic for transient errors (`e.is_transient`)
468+
2. **Use `max_workers`** - Pass `max_workers=3` (or 4) to dispatch 1,000-record chunks concurrently; safe for large datasets where throughput matters more than strict sequential ordering. Dataverse throttles concurrent requests server-side, so values above 4 rarely help and may trigger 429 rate-limiting
469+
3. **Specify select fields** - Limit returned columns to reduce payload size
470+
4. **Control page size** - Use `top` and `page_size` parameters appropriately
471+
5. **Reuse client instances** - Don't create new clients for each operation
472+
6. **Use production credentials** - ClientSecretCredential or CertificateCredential for unattended operations
473+
7. **Error handling** - Implement retry logic for transient errors (`e.is_transient`)
473474
7. **Always include customization prefix** for custom tables/columns
474475
8. **Use lowercase for column names, match `$metadata` for navigation properties** - Column names in `$select`/`$filter`/record payloads use lowercase LogicalNames. Navigation properties in `$expand` and `@odata.bind` keys are case-sensitive and must match the entity's `$metadata` (PascalCase for custom lookups like `new_CustomerId`, lowercase for system lookups like `parentaccountid`)
475476
9. **Test in non-production environments** first

README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,19 @@ client.records.update("account", ids, {"industry": "Technology"})
184184

185185
# Bulk delete
186186
client.records.delete("account", ids, use_bulk_delete=True)
187+
188+
# Concurrent chunk dispatch — max_workers sends chunks in parallel via threads
189+
# Recommended for large datasets when latency matters more than strict ordering
190+
ids = client.records.create("account", payloads, max_workers=3)
191+
client.records.update("account", ids, {"industry": "Technology"}, max_workers=3)
187192
```
188193

189-
> **Large batches**: Lists exceeding 1,000 records are automatically split into sequential
190-
> 1,000-record chunks — no manual pre-splitting needed. Note that chunked operations are
191-
> **not atomic**: a failure mid-way may leave earlier chunks applied. Callers that require
192-
> atomicity should limit their input to ≤ 1,000 records.
194+
> **Large batches**: Lists exceeding 1,000 records are automatically split into 1,000-record
195+
> chunks — no manual pre-splitting needed. By default chunks are dispatched sequentially.
196+
> Pass `max_workers=N` (recommended: 3–4) to send chunks concurrently via threads — useful
197+
> when throughput matters more than strict sequential ordering. Note that chunked operations
198+
> are **not atomic**: a failure mid-way may leave earlier chunks applied. Callers that
199+
> require atomicity should limit their input to ≤ 1,000 records.
193200
194201
### Upsert operations
195202

src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Use the PowerPlatform Dataverse Client Python SDK to interact with Microsoft Dat
2525
- `client.batch` -- batch multiple operations into a single HTTP request
2626

2727
### Bulk Operations
28-
The SDK supports Dataverse's native bulk operations: Pass lists to `create()`, `update()` for automatic bulk processing, for `delete()`, set `use_bulk_delete` when passing lists to use bulk operation
28+
The SDK supports Dataverse's native bulk operations: Pass lists to `create()`, `update()`, or `upsert()` for automatic bulk processing; for `delete()`, set `use_bulk_delete=True`. Lists exceeding 1,000 records are automatically split into 1,000-record chunks — no manual pre-splitting needed. By default chunks are dispatched sequentially; pass `max_workers=N` (recommended: 3–4) to dispatch chunks concurrently via threads. Operations across chunks are **not atomic**: a failure mid-way may leave earlier chunks applied. Callers that require atomicity should limit their input to ≤ 1,000 records.
2929

3030
### Paging
3131
- Control page size with `page_size` parameter

0 commit comments

Comments
 (0)