Skip to content

Repository files navigation

diameter-cc

Diameter Credit-Control Server — Spring Boot 3.5 / Java 21 implementation of the Gy interface (RFC 4006, Application-Id 4) on jdiameter 1.7.x. Real-time prepaid mobile billing with idempotent partial debits, Postgres credit ledger, bundled PDN-Gateway test client, Testcontainers integration suite, Prometheus + Grafana observability.

Java Spring Boot jdiameter Diameter PostgreSQL Testcontainers Prometheus Grafana License: MIT Tests

Live Grafana dashboard — CCR rate, Result-Code breakdown, p50/p95/p99 latency, active sessions

Live dashboard recorded against the running stack — bundled PGW client looping CCR-I → CCR-U → CCR-T at ~1 cycle/2 s. Server: OPEN, all responses Result-Code 2001, p99 well under the 50 ms SLO line. Reproducible via docker compose up && ./mvnw -pl server spring-boot:run plus the bundled diameter-test-client --loop.

What this is

diameter-cc implements the Diameter Gy credit-control flow end-to-end:

  • Peer state machine (CER/CEA, DWR/DWA, DPR/DPA) on TCP :3868
  • CCR-Initial / Update / Terminate handling (RFC 4006 §6)
  • Idempotent partial debits keyed on (Session-Id, CC-Request-Number)
  • Postgres-backed credit account ledger with immutable audit trail
  • Bundled diameter-test-client simulating a PDN Gateway running a 5-minute prepaid call cycle
  • Prometheus metrics + Grafana dashboard with CCR latency histograms and Result-Code breakdowns

Why this pairs with cdr-pipeline

cdr-pipeline and diameter-cc are deliberately built as a pair — same business problem (mobile billing), opposite latency regimes.

Aspect cdr-pipeline diameter-cc
Billing model Post-paid Prepaid
Latency budget Seconds–minutes (batch) <50 ms p99 (real-time)
Trigger CDR file / Kafka after call CCR while call is in progress
Risk if it fails Reconciliation needed User gets free service or call drops
Idempotency key event_id (Session-Id, CC-Request-Number)
Storage MySQL rated + MongoDB raw Postgres credit_account + reservation
Wire protocol Kafka Diameter (TCP, RFC 6733)

Both repos apply the same idempotency discipline — a replayed message is detected by its key and the original answer is returned byte-identically.

Architecture (in progress)

flowchart LR
    A[diameter-test-client<br/>PDN Gateway sim] -- TCP 3868 --> B[jdiameter Stack]
    B -- NetworkReqListener --> C[CreditControlListener]
    C -- AvpCodec.parse --> D[CreditControlRequest]
    D --> E[CreditControlService]
    E --> F[LedgerService]
    F -- @Transactional --> H[(Postgres:<br/>credit_account,<br/>cc_session,<br/>reservation,<br/>ledger_transaction)]
    F --> I[CreditControlAnswer]
    I -- AvpCodec.build --> J[Answer Message]
    J --> B
    B -- CCA-I/U/T --> A
Loading

Quickstart (planned)

git clone git@github.com:soneeee22000/diameter-cc.git
cd diameter-cc
docker compose up -d postgres prometheus grafana
./mvnw spring-boot:run -pl server

# in another terminal:
./mvnw exec:java -pl test-client \
    -Dexec.mainClass=dev.pseonkyaw.diametercctest.DiameterTestClient

Watch the credit balance debit live in Postgres and CCR latency in Grafana at localhost:3001 (anonymous viewer enabled).

What this deliberately does NOT implement

This is a 30-hour weekend portfolio piece. The following are explicit, deliberate cuts:

  • SCTP transport — TCP only (RFC 6733 permits both)
  • IPv6 peer transport — IPv4 only
  • Multi-realm DRA / agent routing — single peer pair
  • Full RFC 4006 §5.7 failure-handling matrix — CCFH and DDFH not implemented
  • Multi-Service-Credit-Control AVP combinatorics — one quota per session (CC-Time)
  • Disk-based session recovery / clustering / HA — single-instance, in-memory peer state
  • 5G SBI HTTP/2 Npcf wrapper — Diameter Gy only
  • TLS / DTLS — plaintext for demo

These are documented gaps, not oversights. Each is a real production concern scoped out to keep the portfolio piece focused and shippable.

Status

Day 1 progress (~30h weekend budget):

  • Block 1 — Maven multi-module scaffold, Spring Boot wiring, jdiameter peer-handshake spike (CER/CEA verified end-to-end)
  • Block 2 — Production CreditControlListener wired into Spring lifecycle
  • Block 3AvpCodec parses CCR-Initial / Update / Termination
  • Block 4 — JPA entities + repositories (CreditAccount, CcSession, Reservation, LedgerTransaction) + Testcontainers wiring
  • Block 5LedgerService transactional reserve / debit / refund primitives
  • Block 6CreditControlService.handleInitial returns CCA-I with quota grant; idempotency cache short-circuits replays
  • Block 7 — End-to-end CCR-Initial integration test (Docker-gated)
  • Day 2 Block 1+2 — CCR-Update + CCR-Terminate full flows (refund of unused, debit of used, optional new grant, session close)
  • Day 2 Block 3 — End-to-end idempotency replay integration test
  • Day 2 Block 5 — Micrometer metrics: diameter_ccr_total{type, result_code}, diameter_ccr_latency_seconds{type} (SLO histogram), diameter_active_sessions, diameter_quota_granted_units_total, diameter_quota_used_units_total, diameter_idempotent_replay_total
  • Day 2 Block 6 — Provisioned Grafana dashboard with 7 panels (server up, active sessions, replays, CCR rate by type, Result-Code breakdown, p50/p95/p99 latency, grant vs use)
  • Day 3 — Live demo verified (server + Postgres + Prometheus + Grafana), README hero GIF embedded, all 25 tests run green against Docker

Test scoreboard: 25 tests, 0 failures, 11 skipped (Docker-gated).

License

MIT — see LICENSE.

About

Diameter Credit-Control Server (Gy / RFC 4006 / App-Id 4) — Spring Boot 3.5, Java 21, jdiameter 1.7.x. Real-time prepaid mobile billing with idempotent partial debits. TRANSATEL Java portfolio.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages