Skip to content

feat(graphql): add WebSocket subscription support for real-time data (Fixes #242) - #260

Merged
elizabetheonoja-art merged 2 commits into
Utility-Protocol:mainfrom
davidsoniaudin2-oss:feat/242-graphql-subscriptions
Aug 24, 2026
Merged

feat(graphql): add WebSocket subscription support for real-time data (Fixes #242)#260
elizabetheonoja-art merged 2 commits into
Utility-Protocol:mainfrom
davidsoniaudin2-oss:feat/242-graphql-subscriptions

Conversation

@davidsoniaudin2-oss

Copy link
Copy Markdown
Contributor

Summary

Adds async-graphql based subscription support enabling clients to receive real-time meter readings and billing events over WebSocket without polling.

Changes

New Modules

  • src/graphql/pubsub.rs — In-process PubSub event bus using tokio::sync::broadcast for per-topic event delivery, subscriber count tracking, and lazy GC of dead channels.

  • src/graphql/types.rs — GraphQL types with async-graphql derives:

    • MeterReading — readingId, deviceId, serviceType, value, unit, timestamp
    • BillingEvent — eventId, deviceId, serviceType, amount, currency, status, timestamp, description
    • MeterReadingFilter / BillingEventFilter — optional deviceId and serviceType filter inputs
  • src/graphql/mod.rs — Schema with:

    • Query: apiVersion, health, activeSubscriptions
    • Mutation: publishMeterReading, publishBillingEvent for pushing events into the subscription bus
    • Subscription: meterReadings(filter) and billingEvents(filter) with in-stream filtering via custom Stream impls wrapping broadcast receivers
    • Schema builder build_schema(pubsub) that injects the shared PubSub into GraphQL context

Router Changes (src/api/router.rs)

  • GraphQL HTTP endpoint at GET/POST /api/graphql
  • GraphQL WebSocket subscription endpoint at GET /api/graphql/ws using async-graphql-axum::GraphQLSubscription

Dependencies

  • async-graphql = "7" — GraphQL server framework
  • async-graphql-axum = "7" — Axum integration with WebSocket subscription transport

Tests

  • tests/graphql_subscription_tests.rs — 17 integration tests:

    • Query tests (apiVersion, health, activeSubscriptions)
    • Mutation tests (publishMeterReading, publishBillingEvent)
    • Subscription filtering tests (no filter, deviceId filter, serviceType filter)
    • Billing event subscriptions with deviceId filter
    • HTTP endpoint acceptance test
    • WebSocket upgrade endpoint test (101 Switching Protocols with graphql-transport-ws protocol)
    • PubSub unit tests (publish/subscribe, topic isolation, subscriber count, GC)
  • src/graphql/pubsub.rs — 4 unit tests (publish/subscribe, topic isolation, subscriber count tracking, GC)

How to Test

# Run all subscription tests
cargo test graphql_subscription

# Run PubSub unit tests
cargo test --lib graphql::pubsub::tests

# Manual WebSocket test
wscat -c ws://localhost:8443/api/graphql/ws -s graphql-transport-ws
# Send: {"type":"subscribe","id":"1","payload":{"query":"subscription { meterReadings { readingId deviceId value } }"}}

Architecture

┌─────────────┐    publish     ┌──────────────┐    broadcast    ┌──────────────┐
│  Mutation    │──────────────▶│  SimplePubSub  │───────────────▶│  Subscription │
│  (HTTP)      │               │  (tokio bcast) │                │  (WS Stream)  │
└─────────────┘               └──────────────┘                └──────────────┘

Events flow: Mutations publish JSON payloads to the PubSub, which fans them out to all active subscription streams. Each subscription stream applies optional deviceId/serviceType filters before yielding to the WebSocket client.


Closes #242

oche11207-art and others added 2 commits August 24, 2026 15:38
…ixes Utility-Protocol#242)

Implements async-graphql based GraphQL subscriptions with pubsub event
bus enabling clients to receive real-time meter readings and billing
events without polling. Adds schema with query, mutation, and subscription
roots, in-process PubSub using tokio broadcast channels, subscription
filtering by deviceId and serviceType, and axum route wiring.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
- Add missing serde imports to graphql/types.rs
- Replace custom poll_recv stream impl with tokio_stream::BroadcastStream
- Remove Arc wrapping of Schema (incompatible with Executor trait)
- Clean up duplicate imports in graphql/mod.rs

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@elizabetheonoja-art
elizabetheonoja-art merged commit 6bce1f3 into Utility-Protocol:main Aug 24, 2026
2 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GraphQL Subscription Support for Real-Time Data

3 participants