feat: add stress tests and CI benchmark integration#298
Merged
Conversation
Add grpc v1.19.0 note
docs(fix): add setup reference to grpcio v1.19.0 package
Fix links
…allowing one query and one mutation Per DGRAPH-2777
fix: small typo error
chore: enabled syntax highlighting
Docs (discuss feedback): fix incorrect statement about upsert blocks allowing one query and one mutation
- Add 6 unit tests verifying the asyncio.Lock deadlock fix - Rename _discard_internal → _locked_discard (communicates lock precondition) - Rename _common_discard → _prepare_discard (in both AsyncTxn and Txn) - Replace assert with RuntimeError for lock-held check (bandit B101)
matthewmcneely
requested changes
Feb 11, 2026
Enable continuous performance tracking by triggering benchmarks on main branch pushes in addition to release tags.
- Remove 1million.rdf.gz and 1million.schema from repo (16MB saved) - Add _downloaded_data_fixture_path() to fetch from dgraph-benchmarks - Add DATA_FIXTURE_DIR and DATA_FIXTURE_BASE_URL configuration - Update .gitignore to exclude downloaded test data
- Replace SYNTHETIC_SCHEMA with movies_schema from dgraph-benchmarks - Add lazy fixture evaluation to only download data when STRESS_TEST_MODE is moderate or full (quick mode skips download entirely) - Support both numeric UIDs and UUIDs in RDF data conversion - Update all test queries/mutations to use movies schema predicates
164be7e to
8f15345
Compare
- sync_client → _sync_client (internal function-scoped) - session_sync_client → sync_client (session-scoped, main client) - sync_client_with_movies_schema → stress_test_sync_client - async_client_with_movies_schema → stress_test_async_client - async_client_with_movies_schema_for_benchmark → stress_test_async_client_for_benchmark
# Conflicts: # .gitignore # .pre-commit-config.yaml # CONTRIBUTING.md # Makefile # PUBLISHING.md # pydgraph/__init__.py # pydgraph/errors.py # pyproject.toml # scripts/local-test.sh # tests/test_async_client.py # tests/test_retry.py # uv.lock
Replace manual suite() functions using makeSuite (removed in Python 3.13) with unittest.main() which handles test discovery automatically.
c7e6233 to
dde7356
Compare
Each test file now defines its own client fixtures instead of sharing them via conftest.py. This makes dependencies explicit and allows shorter, context-appropriate names: - test_stress_sync.py / test_benchmark_sync.py: sync_client - test_stress_async.py: async_client (native) + benchmark_client (sync-wrapped) - test_benchmark_async.py: benchmark_client (sync-wrapped) Also splits the former tuple-returning fixture into separate event_loop and client fixtures, and adds proper type annotations to fix mypy no-untyped-def errors.
dde7356 to
336a5d0
Compare
Remove _sync_client and sync_client_clean fixtures from conftest. Consumers now use session-scoped sync_client with explicit drop_all calls. Also rename movies_schema → movies_schema_path (Path) and movies_schema_content → movies_schema (str) for clarity.
…chmarks by default - Remove async_client_clean fixture; use async_client with explicit drop_all - Convert async stress fixtures to sync (benchmark_event_loop.run_until_complete) to avoid pytest-asyncio ScopeMismatch with module-scoped fixtures - Consolidate stress_client and benchmark_client into single stress_client fixture in test_stress_async.py - Make stress_client module-scoped in both stress test files to reuse across tests - Skip drop_all/schema alter when movies_data_loaded is True (moderate/full modes) - Default PYTEST_ARGS now includes --benchmark-disable for faster test runs
Replace iterations config with rounds parameter that repeats each test's concurrent batch to create sustained load. Tune quick mode (workers=20, ops=200, rounds=50) to achieve ~30s execution time with --benchmark-disable.
- Set GRPC_ENABLE_FORK_SUPPORT=0 in conftest to prevent gRPC atfork crash when pytest-benchmark calls subprocess.fork() to collect machine info while gRPC channels are still open - Change make benchmark to use STRESS_TEST_MODE=quick instead of moderate — the 1M movie dataset overwhelms the local Docker compose cluster when pytest-benchmark runs calibration rounds - Add STRESS_TEST_ROUNDS env var override so make benchmark can set rounds=1, letting pytest-benchmark handle repetition instead of our custom rounds loop
Makefile exports STRESS_TEST_ROUNDS as empty string when not set,
causing int('') ValueError. Use truthiness check instead of
None check to handle both unset and empty cases.
Replace benchmark() with benchmark.pedantic(rounds=1, iterations=1, warmup_rounds=0) in all 13 stress test functions so pytest-benchmark doesn't auto-calibrate and repeat heavy concurrent workloads. This is the proper fix for benchmark timeouts — the stress test's own inner loop (stress_config["rounds"]) already handles repetition, so letting pytest-benchmark compound on top overwhelms the Dgraph cluster. With pedantic() as the primary control: - Remove STRESS_TEST_ROUNDS env var (no longer needed anywhere) - Split benchmark target into two phases with separate Docker clusters (Phase 1 targeted benchmarks do drop_all which destabilises the alpha) - Add _wait_for_alpha_ready() health check after bulk-loading 1M triples - Add LOG variable support for injecting --log-cli-level into pytest - Document benchmark output files in Makefile comments - Add stress-benchmark-results.json to .gitignore
matthewmcneely
approved these changes
Feb 17, 2026
Contributor
|
@mlwelles Can you resolve the conflicts and then merge? |
mlwelles
added a commit
that referenced
this pull request
Feb 25, 2026
## Summary - Bumps VERSION from 25.1.0 to 25.2.0 in `pydgraph/meta.py` - Adds v25.2.0 changelog entry covering 12 commits since v25.1.0 ### Highlights in this release - **Stress tests & CI benchmarks** for performance regression tracking (#298) - **AbortedError pickling fix** for Celery/multiprocessing compatibility (#299) - **asyncio.Lock deadlock fix** in `AsyncTxn.do_request` error handling - Dependabot security vulnerability fixes - CI/CD pipeline improvements ### Verification - `make build` produces `pydgraph-25.2.0.tar.gz` and `pydgraph-25.2.0-py3-none-any.whl` - `make test` passes (219/219) - `trunk fmt CHANGELOG.md` passes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds comprehensive stress tests for sync/async clients and integrates pytest-benchmark into CI. Includes merge of
mainbringing in the picklable AbortedError fix (#299).Stress Tests
retry(),retry_async(),with_retry(),with_retry_async(),run_transaction(),run_transaction_async())_syncor_asyncsuffixes for clear identificationTargeted Benchmarks
Individual operation benchmarks to pinpoint regression root causes:
26 total benchmarks (13 sync + 13 async) - when a stress test regresses, compare individual operation times to identify the exact bottleneck.
Test Resources
movies_schema(),movies_rdf_gz(),movies_rdf()CI Benchmark Integration
benchmarksjob in PR/main CI workflow (STRESS_TEST_MODE=moderate)Makefile Improvements
make test PYTEST_ARGS="..."syntax (exports propagate to scripts)make benchmarkdelegates to test targetPYTEST_ARGS=-v --benchmark-disableStress Test Modes
Each mode uses a
roundsparameter that repeats each test's concurrent batch to create sustained load:quick(default)moderatefullHousekeeping
unittest.makeSuiteusage (removed in Python 3.13)suite()functions withunittest.main()in test files