|
9 | 9 |
|
10 | 10 | Tests |
11 | 11 | ----- |
12 | | -1. Non-blocking reads — canary ticks every 10 ms during GET calls; large gap |
13 | | - means the event loop was blocked. |
14 | | -2. Read throughput — N sequential vs N concurrent reads; confirms GET path |
15 | | - parallelizes. |
16 | | -3. Write concurrency — N sequential vs N concurrent creates; confirms POST |
17 | | - path (different timeout branch) also parallelizes. |
18 | | -4. Pagination non-blocking— canary ticks during list_pages/execute_pages; confirms |
19 | | - async generators yield between page fetches. |
20 | | -5. Mixed fan-out — 6 different operation types fired simultaneously; |
21 | | - catches cross-operation serialization. |
22 | | -6. Error resilience — 3 good + 2 bad calls in gather(return_exceptions=True); |
23 | | - confirms failures don't cancel successful calls. |
24 | | -7. Real-world fan-out — metadata for 6 tables fetched in parallel; end-to-end |
25 | | - validation of the most common async use case. |
| 12 | +1. Non-blocking reads (canary) |
| 13 | + A background task ticks every 10 ms while each GET call runs. A blocking call |
| 14 | + would starve the canary and produce a large gap. Covers records.list, |
| 15 | + tables.list, tables.get, query.sql, query.fetchxml, query.builder. |
| 16 | +
|
| 17 | +2. Read throughput (sequential vs concurrent) |
| 18 | + Runs N reads sequentially then N reads with asyncio.gather(). An internal |
| 19 | + lock or misplaced await would collapse the speedup to ~1x. Covers |
| 20 | + records.list, query.sql, tables.get. |
| 21 | +
|
| 22 | +3. Write concurrency (POST path) |
| 23 | + Same as Test 2 but for records.create(). The POST path uses a different |
| 24 | + timeout branch (120 s vs 10 s for GET), so a separate test ensures writes |
| 25 | + are also truly concurrent. Creates N records in parallel then cleans up. |
| 26 | +
|
| 27 | +4. Pagination non-blocking (async generator canary) |
| 28 | + Runs list_pages(), fetchxml().execute_pages(), and builder().execute_pages() |
| 29 | + while the canary ticks. Confirms the async generator yields control back to |
| 30 | + the event loop between page fetches. |
| 31 | +
|
| 32 | +5. Mixed fan-out (cross-operation concurrency) |
| 33 | + Fires 6 different operation types simultaneously in one gather(). A shared |
| 34 | + internal resource could accidentally serialize different operation types even |
| 35 | + if same-type parallelism works. This test catches cross-operation serialization. |
| 36 | +
|
| 37 | +6. Error resilience |
| 38 | + Fires 5 calls — 3 good, 2 intentionally bad — using gather(return_exceptions=True). |
| 39 | + Confirms the 3 good calls complete despite the 2 failures. Validates that the |
| 40 | + SDK does not suppress exceptions in a way that would break this pattern. |
| 41 | +
|
| 42 | +7. Real-world metadata fan-out |
| 43 | + Fetches schema info for 6 tables sequentially then in parallel. The most |
| 44 | + common real-world async use case: an app needs metadata for several tables |
| 45 | + at startup. Demonstrates the pattern end-to-end with real results. |
26 | 46 |
|
27 | 47 | How to interpret results |
28 | 48 | ------------------------ |
|
0 commit comments