Add spring-aerospike: Aerospike-Java sample with Keploy record/replay#135
Open
Aditya-eddy wants to merge 1 commit into
Open
Add spring-aerospike: Aerospike-Java sample with Keploy record/replay#135Aditya-eddy wants to merge 1 commit into
Aditya-eddy wants to merge 1 commit into
Conversation
Java counterpart of keploy/samples-go/aerospike-tls. A Spring Boot
2.7 service that talks to Aerospike CE on clear-text :3000 via the
aerospike-client-jdk8 driver, recorded and replayed end-to-end with
three bundled scripts that mirror the Go sample's shape one-to-one
(same endpoints, same test-set layout, same scripts).
Endpoints (full parity with the Go sample, 14 total):
GET /health
POST /put GET /get/{key}
POST /batch/put GET /batch/get
POST /scan POST /query
POST /udf POST /cdt/list/append POST /cdt/map/put
POST /touch/{key} DELETE /key/{key}
POST /parallel POST /multiclient POST /freshclient
main.go's concurrency story is ported one-for-one:
* ClientPolicy.maxConnsPerNode = 256, OpeningConnectionThreshold
analogue set to 16 so bursts don't outpace upstream connect rate.
* parallelWrite / parallelRead policies with socketTimeout 10s,
totalTimeout 30s, maxRetries 10, sleepBetweenRetries 5ms.
* Two-phase warmup on the main client at startup — sequential
prelude walks the cluster past cold-start latencies, then a
parallel fill puts idle connections in the pool before the
HTTP server accepts the first request.
* RetryHelper.doOp wraps each PUT and GET in /parallel,
/multiclient, /freshclient.
scripts/ matches the Go sample's pipeline shape (common.sh +
script-{1,2,3}.sh + same env-var knobs: KEPLOY / PORT / LOG_DIR /
SKIP_DOCKER / SKIP_BUILD). Smoke-tested locally with the dev
keploy binary that carries the Aerospike parser:
script-1.sh → test-set-0: 8/8 pass
script-2.sh → test-set-1: 6/6 pass
script-3.sh → test-set-2: 8/8 pass
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new spring-aerospike/ sample application to the repo: a Spring Boot service that uses the Aerospike Java client and includes Keploy-focused scripts to record and replay multiple test-sets (CRUD + concurrency-focused endpoints).
Changes:
- Introduces a Spring Boot 2.7 Aerospike-backed service with CRUD, batch, maintenance, and concurrency endpoints (
/parallel,/multiclient,/freshclient). - Adds Aerospike client configuration (pool sizing + warmup) plus per-operation policies and an app-level retry helper.
- Adds Docker + Keploy config and 3 scripts to run record→replay loops for three separate test-sets.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| spring-aerospike/src/main/resources/application.properties | Configures server port and Aerospike connection/pool + warmup settings. |
| spring-aerospike/src/main/java/com/example/aerospike/util/RetryHelper.java | Adds an app-level retry wrapper used by concurrency endpoints. |
| spring-aerospike/src/main/java/com/example/aerospike/SpringAerospikeApplication.java | Spring Boot application entrypoint. |
| spring-aerospike/src/main/java/com/example/aerospike/dto/PutRequest.java | DTO for /put and other endpoints accepting JSON bins. |
| spring-aerospike/src/main/java/com/example/aerospike/controller/ParallelController.java | Implements single-client concurrent PUT+GET burst endpoint. |
| spring-aerospike/src/main/java/com/example/aerospike/controller/MultiClientController.java | Implements concurrent burst endpoint that round-robins across multiple clients. |
| spring-aerospike/src/main/java/com/example/aerospike/controller/MaintenanceController.java | Implements /touch and /key delete maintenance endpoints. |
| spring-aerospike/src/main/java/com/example/aerospike/controller/HealthController.java | Adds /health endpoint for readiness checks used by scripts. |
| spring-aerospike/src/main/java/com/example/aerospike/controller/FreshClientController.java | Implements concurrent burst endpoint that constructs a new client per worker. |
| spring-aerospike/src/main/java/com/example/aerospike/controller/CrudController.java | Implements CRUD + batch endpoints for recording baseline Aerospike traffic. |
| spring-aerospike/src/main/java/com/example/aerospike/controller/AdvancedController.java | Adds scan/query/udf/cdt endpoints for parity with the Go sample. |
| spring-aerospike/src/main/java/com/example/aerospike/config/Policies.java | Defines tuned read/write policies for bursty concurrency endpoints. |
| spring-aerospike/src/main/java/com/example/aerospike/config/AerospikeProperties.java | Adds Spring @ConfigurationProperties for Aerospike settings. |
| spring-aerospike/src/main/java/com/example/aerospike/config/AerospikeConfig.java | Wires Aerospike clients, builds ClientPolicy, and performs warmup. |
| spring-aerospike/scripts/script-1.sh | Script to record+replay CRUD-focused test-set-0. |
| spring-aerospike/scripts/script-2.sh | Script to record+replay /parallel test-set-1. |
| spring-aerospike/scripts/script-3.sh | Script to record+replay /multiclient + /freshclient test-set-2. |
| spring-aerospike/scripts/common.sh | Shared script helpers for docker boot, build, record, normalize, replay. |
| spring-aerospike/README.md | Documents endpoints, layout, and how to run scripts for record/replay. |
| spring-aerospike/pom.xml | Maven project definition (Spring Boot + Aerospike client dependency). |
| spring-aerospike/keploy.yml | Keploy CLI configuration for recording/testing. |
| spring-aerospike/Dockerfile | Container build for the sample app. |
| spring-aerospike/docker-compose.yml | Spins up Aerospike CE and the sample app. |
| spring-aerospike/aerospike-conf/aerospike.conf | Aerospike server configuration for the sample environment. |
| spring-aerospike/.gitignore | Ignores build artifacts and generated keploy recordings. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+48
to
+51
| // Hold concurrent-open low so a burst doesn't outpace stunnel / | ||
| // the proxy's TLS handshake rate. The Go sample uses the same | ||
| // 16 ceiling for the same reason. | ||
| policy.asyncMaxConnsPerNode = props.getOpeningConnectionThreshold(); |
Comment on lines
+115
to
+117
| } catch (Throwable t) { | ||
| log.warn("warmup failed (non-fatal): {}", t.toString()); | ||
| } |
| -H 'Content-Type: application/json' \ | ||
| -d '[{"key":"a","bins":{"n":1}},{"key":"b","bins":{"n":2}}]' | ||
| sleep 1 | ||
| curl -s -o /dev/null "http://127.0.0.1:$PORT/batch/get?k=a&k=b" || true |
Comment on lines
+47
to
+51
| policy.asyncMaxConnsPerNode = props.getConnectionQueueSize(); | ||
| // Hold concurrent-open low so a burst doesn't outpace stunnel / | ||
| // the proxy's TLS handshake rate. The Go sample uses the same | ||
| // 16 ceiling for the same reason. | ||
| policy.asyncMaxConnsPerNode = props.getOpeningConnectionThreshold(); |
Comment on lines
+37
to
+38
| throw last; | ||
| } |
Comment on lines
+45
to
+49
| Statement stmt = new Statement(); | ||
| stmt.setNamespace(props.getNamespace()); | ||
| stmt.setSetName(props.getSet()); | ||
| stmt.setFilter(Filter.range("age", 0, 99)); | ||
| int count = 0; |
Comment on lines
+58
to
+62
| @PostMapping("/udf") | ||
| public Map<String, Object> udf(@RequestBody PutRequest req) { | ||
| Key k = new Key(props.getNamespace(), props.getSet(), req.getKey()); | ||
| Object out = client.execute(null, k, "transform", "apply", Value.get("bin"), Value.get(1)); | ||
| return Map.of("result", out == null ? "null" : out.toString()); |
Comment on lines
+67
to
+73
| sudo pkill -SIGINT keploy 2>/dev/null || true | ||
| for _ in $(seq 1 15); do | ||
| if ! pgrep -af "keploy record" >/dev/null 2>&1; then return 0; fi | ||
| sleep 1 | ||
| done | ||
| echo "WARN: keploy didn't exit on SIGINT, killing" | ||
| sudo pkill -KILL keploy 2>/dev/null || true |
| import java.util.Map; | ||
|
|
||
| /** | ||
| * The four extra endpoints that the Go sample carries — /scan, |
|
|
||
| | Method | Path | What it does | | ||
| | ------ | -------------------------- | ---------------------------------------------------------------------------- | | ||
| | GET | `/health` | `info build + namespaces` | |
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
spring-aerospike/sample — Spring Boot 2.7 +aerospike-client-jdk8, talks to Aerospike CE on clear-text 3000.keploy/samples-go/aerospike-tls. Endpoints and concurrency knobs are a one-to-one port (14 endpoints, two-phase warmup, generous per-op policy, app-level retry wrapper).scripts/script-{1,2,3}.sh) that record + replay one test-set each: CRUD,/parallel,/multiclient+/freshclient.keploy/— every script regenerates the test-set, so every CI run validates the full record→replay loop.Depends on the Aerospike parser landing in keploy: keploy/keploy#4190 + keploy/integrations#194.
Test plan
mvn -q -DskipTests packagecleandocker compose up -d aerospikehealthy./scripts/script-1.sh→ test-set-0: 8/8 pass./scripts/script-2.sh→ test-set-1: 6/6 pass (/parallel?n=24included)./scripts/script-3.sh→ test-set-2: 8/8 pass (/multiclient?n=24+/freshclient?n=8)All three scripts validated locally with the dev keploy binary carrying the Aerospike parser before pushing.
🤖 Generated with Claude Code