Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ Split what you write by *kind*, so each doc keeps exactly one job:
history-worthy goes here: what changed and *why*, dated milestones, gotchas
discovered, schema/protocol bugs, superseded decisions. Never rewrite or
delete an old entry; supersede it with a new dated one.
- **`README.md`** — only if a *user-facing* fact changed (shipped feature,
public API, test numbers). Most commits won't touch it.
- **`README.md`** — **check it after every commit.** If a *user-facing* fact
changed (shipped feature, public API, test numbers, step/milestone status),
update it in the same commit so it never drifts from STATUS.md.

If a commit is a legitimate pure docs catch-up (reconciling a prior
source-only commit), bypass with `git commit --no-verify` — but that should be
Expand Down
35 changes: 35 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ if(GTest_FOUND)
tests/unit/ContainsKeyTest.cpp
tests/unit/HashAwareRoutingTest.cpp
tests/unit/ErrorHandlingTest.cpp
tests/unit/ServerSelectionTest.cpp
)

target_link_libraries(unit_tests
Expand Down Expand Up @@ -285,6 +286,30 @@ if(GTest_FOUND)
# Note: NOT gtest_main - we provide our own main()
)

# RetryView (Step 11b user-decided retry) integration tests (multi-server)
add_executable(retryview_integration_tests
tests/integration/RetryViewIntegrationTest.cpp
)

target_link_libraries(retryview_integration_tests
PRIVATE
hotrod-client
GTest::gtest
# Note: NOT gtest_main - we provide our own main()
)

# Ping keyless-op retry (Step 11c) integration tests (multi-server)
add_executable(pingretry_integration_tests
tests/integration/PingRetryIntegrationTest.cpp
)

target_link_libraries(pingretry_integration_tests
PRIVATE
hotrod-client
GTest::gtest
# Note: NOT gtest_main - we provide our own main()
)

add_test(NAME PingIntegrationTests COMMAND ping_integration_tests)
add_test(NAME GetIntegrationTests COMMAND get_integration_tests)
add_test(NAME GetWithMetadataIntegrationTests COMMAND getwithmetadata_integration_tests)
Expand All @@ -300,6 +325,8 @@ if(GTest_FOUND)
add_test(NAME ConcurrentClientsTests COMMAND concurrent_clients_tests)
add_test(NAME HashAwareRoutingIntegrationTests COMMAND hash_aware_routing_integration_tests)
add_test(NAME ConcurrentMultiServerTests COMMAND concurrent_multiserver_tests)
add_test(NAME RetryViewIntegrationTests COMMAND retryview_integration_tests)
add_test(NAME PingRetryIntegrationTests COMMAND pingretry_integration_tests)

# Set working directory so scripts can be found
set_tests_properties(PingIntegrationTests PROPERTIES
Expand Down Expand Up @@ -362,6 +389,14 @@ if(GTest_FOUND)
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
LABELS "integration;docker;concurrent;multi-server"
)
set_tests_properties(RetryViewIntegrationTests PROPERTIES
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
LABELS "integration;docker;topology;multi-server;retry"
)
set_tests_properties(PingRetryIntegrationTests PROPERTIES
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
LABELS "integration;docker;topology;multi-server;retry"
)
endif() # NOT WIN32 (integration tests)

message(STATUS "Google Test found - unit tests enabled (integration tests: non-Windows only)")
Expand Down
60 changes: 40 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

A cross-platform C++17 implementation of the Infinispan Hot Rod protocol client.

🎉 **Hash-Aware Routing Complete!** - Smart client with automatic failover.
🎉 **Smart client** - hash-aware routing, automatic failover, full CRUD +
metadata ops, typed error handling and user-decided retry (keyed & keyless).

## Quick Start

Expand Down Expand Up @@ -45,6 +46,10 @@ The quickstart demonstrates:
- REMOVE operations (deleting entries)
- Clean disconnect

A second example, `retry.cpp`, demonstrates the user-decided retry loop
(`cache.excluding(e)` on a caught `HotRodClientException`) for both keyed
operations and keyless `ping`.

See [`examples/quickstart/README.md`](examples/quickstart/README.md) for full documentation.

## Building
Expand Down Expand Up @@ -109,7 +114,7 @@ ctest -C Release --output-on-failure

## Testing

### Unit Tests (155 tests)
### Unit Tests (204 tests)
```bash
cd build
./unit_tests
Expand All @@ -118,18 +123,20 @@ cd build
ctest -R UnitTests --output-on-failure
```

### Integration Tests (38 tests)
### Integration Tests (84 tests, 17 suites)
Requires Docker to run Infinispan server:
```bash
cd build

# Run all integration tests (starts server automatically)
# Run all integration tests (starts server automatically) — representative subset:
./ping_integration_tests
./get_integration_tests
./get_integration_tests
./put_integration_tests
./remove_integration_tests
./topology_integration_tests # Multi-node cluster tests
./topology_integration_tests # Multi-node cluster tests
./hash_aware_routing_integration_tests # Smart routing tests
./retryview_integration_tests # User-decided retry (keyed)
./pingretry_integration_tests # User-decided retry (keyless ping)

# Or run all via CTest
ctest --output-on-failure
Expand All @@ -143,18 +150,20 @@ ctest --output-on-failure
> Design rationale is in [docs/DECISIONS.md](docs/DECISIONS.md).

**Current Progress**: Full CRUD (PING/GET/PUT/REMOVE) + SCRAM auth + topology
awareness + hash-aware routing + async multiplexing — all shipped. **Next:**
metadata / version-based operations (Step 10). See [docs/STATUS.md](docs/STATUS.md)
for live status. Per-step milestone history (frozen at Step 9) is archived at
awareness + hash-aware routing + async multiplexing + metadata/version-based
operations (Step 10) + typed error handling and user-decided retry, keyed and
keyless (Step 11) — all shipped. **Next:** bulk operations (Step 12) or
multiplexing benchmarks. See [docs/STATUS.md](docs/STATUS.md) for live status.
Per-step milestone history (frozen at Step 9) is archived at
[docs/archive/PROGRESS.md](docs/archive/PROGRESS.md).

_(Step numbers follow [`../hotrod-foundry/ROADMAP.md`](../hotrod-foundry/ROADMAP.md);
[`docs/STATUS.md`](docs/STATUS.md) is authoritative for which steps are done — not
any headline count.)_

**Test Results** (verified 2026-09-16):
- Unit Tests: **145/145 passing** ✅
- Integration Tests: **46/46 passing** ✅ (against live Infinispan via Docker)
**Test Results** (verified 2026-09-25):
- Unit Tests: **204/204 passing** ✅
- Integration Tests: **84/84 passing** ✅ across 17 suites (against live Infinispan via Docker)

## Features

Expand All @@ -174,6 +183,12 @@ any headline count.)_
- ✅ **GET operation** (read from cache with failover)
- ✅ **PUT operation** (write to cache with lifespan/maxIdle)
- ✅ **REMOVE operation** (delete from cache)
- ✅ **Metadata / version-based operations** (`getWithMetadata`, `putIfAbsent`,
`replace`, `containsKey`, `removeWithVersion`, `replaceWithVersion`) (Step 10)
- ✅ **Typed error handling** (`HotRodClientException` with phase / server status /
tried nodes) + `isTransient` / `outcomeUncertain` classification (Step 11a)
- ✅ **User-decided retry** (`cache.excluding(e)` bound view) for keyed ops and
keyless `ping`, with automatic before-send failover (Step 11b/11c)
- ✅ **Integration test framework** (GoogleTest + Docker + multi-node clusters)

### Full CRUD with Smart Routing and Async Operations
Expand Down Expand Up @@ -217,10 +232,11 @@ for (int i = 0; i < 1000; i++) {
> the 1–3 immediate items in
> [⏭ Next steps](docs/STATUS.md#-next-steps-start-here). This is just a summary.

- **Step 10 — Metadata / version-based operations** (next): `getWithMetadata`,
`replaceWithVersion`, `removeWithVersion`, `putIfAbsent`, `containsKey`
- **Step 11 — Error handling**: ERROR response parsing, exception hierarchy, retries
- **Step 12 — Bulk operations**: `GET_ALL`, `PUT_ALL`, `BULK_GET`
- ✅ **Step 10 — Metadata / version-based operations** (shipped): `getWithMetadata`,
`replaceWithVersion`, `removeWithVersion`, `putIfAbsent`, `replace`, `containsKey`
- ✅ **Step 11 — Error handling** (shipped): ERROR response parsing, typed exception,
user-decided retry (keyed + keyless)
- **Step 12 — Bulk operations** (next): `GET_ALL`, `PUT_ALL`, `BULK_GET`
- Also: multiplexing benchmarks, TLS/SSL support

## Project Structure
Expand All @@ -246,8 +262,8 @@ cpp17-client/
│ ├── hash/ # MurmurHash3 + consistent hashing
│ └── operations/ # Hot Rod operations (with failover)
├── tests/ # Test suite
│ ├── unit/ # 155 unit tests
│ └── integration/ # 38 integration tests (multi-node clusters)
│ ├── unit/ # 204 unit tests
│ └── integration/ # 84 integration tests, 17 suites (multi-node clusters)
├── examples/ # Usage examples
│ └── quickstart/ # Simple GET/PUT/REMOVE example
├── scripts/ # Test infrastructure
Expand Down Expand Up @@ -317,10 +333,14 @@ In short, following the hotrod-foundry porting guidelines:
- ✅ **v0.5.0** (2026-06-12): REMOVE operation complete (Step 9) - **Full CRUD!**
- ✅ **v0.6.0** (2026-06-17): Topology awareness (Step 4)
- ✅ **v0.7.0** (2026-06-17): Hash-aware routing with failover - **Smart Client!**
- 🎯 **v0.8.0** (upcoming): Metadata operations (Step 10)
- ✅ **v0.8.0** (2026-09-20): Metadata / version-based operations (Step 10)
- ✅ **v0.9.0** (2026-09-25): Typed error handling + user-decided retry, keyed &
keyless (Step 11)
- 🎯 **v0.10.0** (upcoming): Bulk operations (Step 12)

---

**Maintained by**: rigazilla
**Status**: Active development
**Current Step**: Hash-aware routing complete! Smart client with automatic failover. ✅
**Current Step**: Error handling + user-decided retry complete (Step 11, keyed &
keyless). Next: bulk operations (Step 12). ✅
Loading
Loading