cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
graphql_ws.h File Reference

GraphQL subscriptions over the graphql-ws WebSocket subprotocol (supported since v3.8). More...

#include <cwist/net/graphql/graphql.h>
#include <cwist/sys/io/reactor.h>
#include <cjson/cJSON.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Include dependency graph for graphql_ws.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct cwist_graphql_ws cwist_graphql_ws_t
 
typedef struct cwist_graphql_event_source cwist_graphql_event_source_t
 
typedef cwist_graphql_event_source_t *(* cwist_graphql_subscribe_fn) (const cJSON *args, const cJSON *variables, void *ctx)
 

Functions

cwist_graphql_ws_t * cwist_graphql_ws_create (cwist_graphql_schema_t *schema)
 Create a graphql-ws endpoint holding a subscription field registry.
 
void cwist_graphql_ws_destroy (cwist_graphql_ws_t *gws)
 Destroy an endpoint and its subscription field registry.
 
bool cwist_graphql_ws_add_subscription (cwist_graphql_ws_t *gws, const char *field, cwist_graphql_subscribe_fn subscribe_fn, void *ctx)
 Register (or replace) the resolver for a subscription root field.
 
bool cwist_graphql_ws_attach (cwist_graphql_ws_t *gws, int fd, cwist_reactor_t *reactor, const uint8_t *initial, size_t initial_len)
 
cwist_graphql_event_source_t * cwist_graphql_event_source_create (void)
 Create an empty event source (topic interest set).
 
bool cwist_graphql_event_source_add_topic (cwist_graphql_event_source_t *src, const char *topic)
 Add a topic to an event source.
 
void cwist_graphql_event_source_destroy (cwist_graphql_event_source_t *src)
 Destroy an event source, freeing all topic strings and the set.
 
size_t cwist_graphql_publish (const char *topic, const cJSON *payload)
 

Detailed Description

GraphQL subscriptions over the graphql-ws WebSocket subprotocol (supported since v3.8).

Implements the graphql-transport-ws subprotocol on top of the non-blocking WebSocket transport (cwist/net/websocket/websocket_async.h): connection_init -> connection_ack, subscribe -> one next message per published event -> complete on unsubscribe, error on operation failure, and ping/pong keepalive at any time after init.

Subscription fields resolve through the same schema/resolver model as queries and mutations: a subscription resolver returns an event source (a set of broker topics) and application code fans events out with cwist_graphql_publish(). The broker is in-process and thread-safe: publish may be called from any thread; delivery to the wire happens on the owning reactor thread.

Opt-in only; no existing behavior changes when unused. Requires the C1M (callback-shaped) WebSocket path.

Definition in file graphql_ws.h.

Typedef Documentation

◆ cwist_graphql_event_source_t

typedef struct cwist_graphql_event_source cwist_graphql_event_source_t

Definition at line 34 of file graphql_ws.h.

◆ cwist_graphql_subscribe_fn

typedef cwist_graphql_event_source_t *(* cwist_graphql_subscribe_fn) (const cJSON *args, const cJSON *variables, void *ctx)

Subscription field resolver. Invoked once per incoming subscribe operation (on the reactor thread).

Parameters
argsParsed root-field arguments (cJSON object) or NULL when none. Borrowed: do not store or free.
variablesThe subscribe message's variables member (borrowed, may be NULL).
ctxOpaque pointer registered with cwist_graphql_ws_add_subscription().
Returns
A newly created event source expressing the topics this operation listens to, or NULL to reject the operation (the client receives an error message).

Definition at line 46 of file graphql_ws.h.

◆ cwist_graphql_ws_t

typedef struct cwist_graphql_ws cwist_graphql_ws_t

Definition at line 33 of file graphql_ws.h.

Function Documentation

◆ cwist_graphql_event_source_add_topic()

bool cwist_graphql_event_source_add_topic ( cwist_graphql_event_source_t *  src,
const char *  topic 
)

Add a topic to an event source.

Register interest in a broker topic. Events published to topic are delivered to every active subscription whose event source lists it. Returns false on invalid input or allocation failure.

Idempotent: adding a topic that is already present succeeds without duplicating it. The topic string is copied, so the caller keeps ownership of topic.

Parameters
srcEvent source to modify; must not be NULL.
topicTopic name to add; must be a non-empty string.
Returns
true on success (including the already-present case), false on invalid arguments or allocation failure.

Definition at line 76 of file graphql_ws.c.

References cap, cwist_alloc_array(), cwist_free(), and cwist_strdup().

◆ cwist_graphql_event_source_create()

cwist_graphql_event_source_t * cwist_graphql_event_source_create ( void  )

Create an empty event source (topic interest set).

Create an empty event source for use as a subscription resolver's return value.

Returns
New event source, or NULL on allocation failure. Owned by the caller; free with cwist_graphql_event_source_destroy().

Definition at line 60 of file graphql_ws.c.

References cwist_alloc().

◆ cwist_graphql_event_source_destroy()

void cwist_graphql_event_source_destroy ( cwist_graphql_event_source_t *  src)

Destroy an event source, freeing all topic strings and the set.

Destroy an event source. Called automatically for active subscriptions when their operation ends (client complete, socket close) or the endpoint is destroyed.

Parameters
srcEvent source to free; NULL is a no-op.

Definition at line 101 of file graphql_ws.c.

References cap, and cwist_free().

◆ cwist_graphql_publish()

size_t cwist_graphql_publish ( const char *  topic,
const cJSON *  payload 
)

Publish an event to the in-process broker. The payload becomes the field value inside each delivered next message's data (null when payload is NULL). Thread-safe: may be called from any thread; matched subscriptions are queued and delivered on their connection's reactor thread.

Parameters
topicBroker topic (non-empty string).
payloadEvent payload (borrowed) or NULL.
Returns
Number of next messages queued.

Definition at line 468 of file graphql_ws.c.

References cap, cwist_alloc_array(), and cwist_free().

◆ cwist_graphql_ws_add_subscription()

bool cwist_graphql_ws_add_subscription ( cwist_graphql_ws_t *  gws,
const char *  field,
cwist_graphql_subscribe_fn  subscribe_fn,
void *  ctx 
)

Register (or replace) the resolver for a subscription root field.

Register or replace a subscription field resolver on the endpoint.

If the field is already registered, its resolver and context are replaced in place; otherwise a new entry is prepended to the registry. The field name is copied.

Parameters
gwsEndpoint to register on; must not be NULL.
fieldSubscription root field name; must be a non-empty string.
subscribe_fnResolver invoked per subscribe for field; must not be NULL. It receives the parsed arguments and variables and returns an event source (owned by the broker) or NULL to reject the operation.
ctxOpaque pointer passed through to subscribe_fn.
Returns
true on success, false on invalid arguments or allocation failure.

Definition at line 190 of file graphql_ws.c.

References cap, cwist_alloc(), cwist_free(), and cwist_strdup().

◆ cwist_graphql_ws_attach()

bool cwist_graphql_ws_attach ( cwist_graphql_ws_t *  gws,
int  fd,
cwist_reactor_t *  reactor,
const uint8_t *  initial,
size_t  initial_len 
)

Attach the graphql-ws protocol handler to a connected, upgraded fd. The fd is driven reactively by reactor (same ownership contract as cwist_websocket_async_attach): the HTTP layer must not touch the fd after a successful call.

Parameters
gwsEndpoint whose schema resolves subscriptions.
fdConnected client socket (set non-blocking here).
reactorReactor that will own the connection.
initialBytes already read past the upgrade request (may be NULL).
initial_lenNumber of valid bytes at initial.
Returns
true when the fd was handed to the reactor path, false on failure (fd closed).

Definition at line 730 of file graphql_ws.c.

References cap, and cwist_websocket_async_attach_ex().

◆ cwist_graphql_ws_create()

cwist_graphql_ws_t * cwist_graphql_ws_create ( cwist_graphql_schema_t *  schema)

Create a graphql-ws endpoint holding a subscription field registry.

Create a graphql-ws endpoint bound to schema. The schema is not owned and must outlive the endpoint.

Parameters
schemaGraphQL schema the endpoint answers to; not owned, must outlive the endpoint.
Returns
New endpoint, or NULL if schema is NULL or allocation fails. Free with cwist_graphql_ws_destroy().

Definition at line 144 of file graphql_ws.c.

References cap, and cwist_alloc().

◆ cwist_graphql_ws_destroy()

void cwist_graphql_ws_destroy ( cwist_graphql_ws_t *  gws)

Destroy an endpoint and its subscription field registry.

Destroy an endpoint and free all subscription field registrations. Must be called only after every connection attached to the endpoint has been torn down (i.e. after the owning reactors have stopped); active connections keep the endpoint alive from the protocol layer's point of view and must be gone first.

Does not touch active connections or broker operations still referencing the endpoint's resolvers.

Parameters
gwsEndpoint to free; NULL is a no-op.

Definition at line 162 of file graphql_ws.c.

References cap, and cwist_free().