Interface QueryBus

All Superinterfaces:
DescribableComponent, QueryHandlerRegistry<QueryBus>
All Known Implementing Classes:
DistributedQueryBus, InterceptingQueryBus, SimpleQueryBus, TenantAwareQueryBus, TracingQueryBus

public interface QueryBus extends QueryHandlerRegistry<QueryBus>, DescribableComponent
The mechanism that dispatches queries to their appropriate query handler.

Query handlers can subscribe to the query bus to handle queries matching the QualifiedName.

Hence, queries dispatched (through either query(QueryMessage, ProcessingContext), query(QueryMessage, ProcessingContext), and subscriptionQuery(QueryMessage, ProcessingContext, int)) match a subscribed query handler based on "query name".

There may be multiple handlers for each query.

Since:
3.1.0
Author:
Marc Gathier, Allard Buijze
  • Method Details

    • query

      Dispatch the given query to a QueryHandler subscribed to the given query's query name, returning a MessageStream of responses to the given query.

      The resulting MessageStream will contain 0, 1, or N QueryResponseMessages, depending on the QueryHandler that handled the given query.

      As several QueryHandlers can be registered for the same query name, this method will loop through them (in insert order) until one has a suitable return value. A suitable response is any value or user exception returned from a QueryHandler. When no handlers are available that can answer the given query, the returned MessageStream will have failed with a NoHandlerForQueryException.

      Parameters:
      query - the query to dispatch
      context - the processing context under which the query is being published (can be null)
      Returns:
      a MessageStream containing either 0, 1, or N QueryResponseMessages
      Throws:
      NoHandlerForQueryException - when no QueryHandler is registered for the given query's query name
    • subscriptionQuery

      MessageStream<QueryResponseMessage> subscriptionQuery(QueryMessage query, @Nullable ProcessingContext context, int updateBufferSize)
      Dispatch the given query to a single QueryHandler subscribed to the given query's queryName/initialResponseType/updateResponseType. The result is lazily created and there will be no execution of the query handler before there is a subscription to the initial result. In order not to miss update, the query bus will queue all update which happen after the subscription query is done and once the subscription to the flux is made, these update will be emitted.

      If there is an error during retrieving or consuming initial result, stream for incremental update is NOT interrupted.

      If there is an error during emitting an update, subscription is cancelled causing further emits not reaching the destination.

      If a subscription query with the same query identifier is already registered, the returned MessageStream will be failed with a SubscriptionQueryAlreadyRegisteredException instead of throwing the exception. This allows callers to handle double subscription scenarios gracefully through the stream API.

      Parameters:
      query - the subscription query to dispatch
      context - the processing context under which the query is being published (can be null)
      updateBufferSize - the size of the buffer which accumulates update
      Returns:
      query result containing initial result and incremental update, or a failed MessageStream with SubscriptionQueryAlreadyRegisteredException if a subscription with the same query identifier already exists
    • subscribeToUpdates

      MessageStream<SubscriptionQueryUpdateMessage> subscribeToUpdates(QueryMessage query, int updateBufferSize)
      Subscribes the given query with the given updateBufferSize, and returns the MessageStream that provides the update of the subscription query.

      Can be used directly instead when fine-grained control of update handlers is required. If using the update directly is not mandatory for your use case, we strongly recommend using subscriptionQuery(QueryMessage, ProcessingContext, int) instead.

      Note that the returned MessageStream must be consumed from before the buffer fills up. Once the buffer is full, any attempt to add an update will complete the stream with an exception.

      If a subscription query with the same query identifier is already registered, the returned MessageStream will be failed with a SubscriptionQueryAlreadyRegisteredException instead of throwing the exception.

      Parameters:
      query - the subscription query for which we register an update handler
      updateBufferSize - the size of the buffer that accumulates update
      Returns:
      a MessageStream of update for the given subscription query, or a failed MessageStream with SubscriptionQueryAlreadyRegisteredException if a subscription with the same query identifier already exists
    • emitUpdate

      CompletableFuture<Void> emitUpdate(Predicate<QueryMessage> filter, Supplier<SubscriptionQueryUpdateMessage> updateSupplier, @Nullable ProcessingContext context)
      Emits the outcome of the updateSupplier to subscription queries matching the given queryName and given filter.
      Parameters:
      filter - a predicate filtering on QueryMessages. The updateSupplier will only be sent to subscription queries matching this filter
      updateSupplier - the update supplier to emit for subscription queries matching the given filter
      context - the processing context under which the updateSupplier is being emitted (can be null)
      Returns:
      a future completing whenever the updateSupplier has been emitted
    • emitUpdateAndCount

      default CompletableFuture<OptionalInt> emitUpdateAndCount(Predicate<QueryMessage> filter, Supplier<SubscriptionQueryUpdateMessage> updateSupplier, @Nullable ProcessingContext context)
      Emits the outcome of the updateSupplier to subscription queries matching the given queryName and given filter, returning the number of subscription queries the update was emitted to.

      Implementations that cannot determine this number return OptionalInt.empty() instead.

      A subscription query to which delivery of the update fails (for example due to a full update buffer) is excluded from this count, even though that failure still terminates the subscription.

      Parameters:
      filter - a predicate filtering on QueryMessages. The updateSupplier will only be sent to subscription queries matching this filter
      updateSupplier - the update supplier to emit for subscription queries matching the given filter
      context - the processing context under which the updateSupplier is being emitted (can be null)
      Returns:
      a future completing with the number of subscription queries the update was emitted to as an OptionalInt, which is empty when we couldn't match
    • completeSubscriptions

      CompletableFuture<Void> completeSubscriptions(Predicate<QueryMessage> filter, @Nullable ProcessingContext context)
      Completes subscription queries matching the given filter.

      To be used whenever there are no subsequent update to emit left.

      Parameters:
      filter - a predicate filtering on QueryMessages. Subscription queries matching this filter will be completed
      context - the processing context within which to complete subscription queries (can be null)
      Returns:
      a future completing whenever all matching subscription queries have been completed
    • completeSubscriptionsAndCount

      default CompletableFuture<OptionalInt> completeSubscriptionsAndCount(Predicate<QueryMessage> filter, @Nullable ProcessingContext context)
      Completes subscription queries matching the given filter, returning the number of subscription queries that were completed.

      Implementations that cannot determine this number return OptionalInt.empty() instead.

      A subscription query for which completion fails is excluded from this count.

      Parameters:
      filter - a predicate filtering on QueryMessages. Subscription queries matching this filter will be completed
      context - the processing context within which to complete subscription queries (can be null)
      Returns:
      a future completing with the number of subscription queries that were completed as an OptionalInt, which is empty when we couldn't match
    • completeSubscriptionsExceptionally

      CompletableFuture<Void> completeSubscriptionsExceptionally(Predicate<QueryMessage> filter, Throwable cause, @Nullable ProcessingContext context)
      Completes subscription queries matching the given filter exceptionally with the given cause.

      To be used whenever emitting update should be stopped due to some exception.

      Parameters:
      filter - a predicate filtering on QueryMessages. Subscription queries matching this filter will be completed exceptionally
      cause - the cause of an error
      context - the processing context within which to complete subscription queries exceptionally (can be null)
      Returns:
      a future completing whenever all matching subscription queries have been completed exceptionally
    • completeSubscriptionsExceptionallyAndCount

      default CompletableFuture<OptionalInt> completeSubscriptionsExceptionallyAndCount(Predicate<QueryMessage> filter, Throwable cause, @Nullable ProcessingContext context)
      Completes subscription queries matching the given filter exceptionally with the given cause, returning the number of subscription queries that were completed exceptionally.

      Implementations that cannot determine this number return OptionalInt.empty() instead.

      A subscription query for which the exceptional completion fails to be delivered is excluded from this count.

      Parameters:
      filter - a predicate filtering on QueryMessages. Subscription queries matching this filter will be completed exceptionally
      cause - the cause of an error
      context - the processing context within which to complete subscription queries exceptionally (can be null)
      Returns:
      a future completing with the number of subscription queries that were completed exceptionally as an OptionalInt, which is empty when we couldn't match