All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.cloud.pubsub.Subscriber Maven / Gradle / Ivy

Go to download

High performance Cloud Pub/Sub client library. (NOTE) This release includes only data plane operations, publishing and pulling messages, and it is based on our gRPC beta release. (ALPHA) This library uses features that are part of an invitation-only release of the underlying Cloud Pub/Sub API. The library will generate errors unless you have access to this API. This restriction should be relaxed in the near future. Please contact [email protected] with any questions in the meantime.

There is a newer version: 0.2.1-EXPERIMENTAL
Show newest version
/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.cloud.pubsub;

import com.google.auth.Credentials;
import com.google.cloud.pubsub.Subscriber.MessageReceiver.AckReply;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.Service;
import com.google.pubsub.v1.PubsubMessage;
import io.grpc.Channel;
import java.util.concurrent.ScheduledExecutorService;
import org.joda.time.Duration;

/**
 * A Cloud Pub/Sub subscriber that is
 * associated with a specific subscription at creation.
 *
 * 

A {@link Subscriber} allows you to provide an implementation of a {@link MessageReceiver * receiver} to which messages are going to be delivered as soon as they are received by the * subscriber. The delivered messages then can be {@link AcknowledgeHandler#ack() acked} or {@link * AcknowledgeHandler#nack() nacked} at will as they get processed by the receiver. Nacking a * messages implies a later redelivery of such message. * *

The subscriber handles the ack management, by automatically extending the ack deadline while * the message is being processed, to then issue the ack or nack of such message when the processing * is done. Note: message redelivery is still possible. * *

It also provides customizable options that control: * *

    *
  • Ack deadline extension: such as the amount of time ahead to trigger the extension of * message acknowledgement expiration. *
  • Flow control: such as the maximum outstanding messages or maximum outstanding bytes to keep * in memory before the receiver either ack or nack them. *
* *

If no credentials are provided, the {@link Publisher} will use application default * credentials through {@link GoogleCredentials#getApplicationDefault}. * *

For example, a {@link Subscriber} can be constructed and used to receive messages as follows: * *

 *  MessageReceiver receiver =
 *      message -> {
 *        // ... process message ...
 *        return Futures.immediateFuture(AckReply.ACK);
 *      });
 *
 *  Subscriber subscriber =
 *      Subscriber.Builder.newBuilder(MY_SUBSCRIPTION, receiver)
 *          .setMaxBatchAcks(100)
 *          .build();
 *
 *  subscriber.startAsync();
 *
 *  ... recommended, listen for fatal errors that break the subscriber streaming ...
 *  subscriber.addListener(
        new Listener() {
          @Override
          public void failed(State from, Throwable failure) {
            System.out.println("Subscriber faile with error: " + failure);
          }
        },
        Executors.newSingleThreadExecutor());
 *
 *  ... and when done with the subscriber ...
 *  subscriber.stopAsync();
 * 
*/ public interface Subscriber extends Service { static final String PUBSUB_API_ADDRESS = "pubsub.googleapis.com"; static final String PUBSUB_API_SCOPE = "https://www.googleapis.com/auth/pubsub"; /** Retrieves a snapshot of the current subscriber statistics. */ SubscriberStats getStats(); /** Users of the {@link Subscriber} must implement this interface to receive messages. */ interface MessageReceiver { public static enum AckReply { /** * To be used for acking a message. */ ACK, /** * To be used for nacking a message. */ NACK } /** * Called when a message is received by the subscriber. * * @return A future that signals when a message has been processed. */ ListenableFuture receiveMessage(PubsubMessage message); } /** Subscription for which the subscriber is streaming messages. */ String getSubscription(); /** * Time before a message is to expire when the subscriber is going to attempt to renew its ack * deadline. */ Duration getAckExpirationPadding(); /** * Maximum number of outstanding (i.e. pending to process) messages before limits are enforced. * *

When limits are enforced, no more messages will be dispatched to the {@link * MessageReceiver} but due to the gRPC and HTTP/2 buffering and congestion control window * management, still some extra bytes could be kept at lower layers. */ Optional getMaxOutstandingMessages(); /** * Maximum number of outstanding (i.e. pending to process) bytes before limits are enforced. */ Optional getMaxOutstandingBytes(); /** Builder of {@link Subscriber Subscribers}. */ public static final class Builder { static final Duration MIN_ACK_EXPIRATION_PADDING = Duration.millis(100); static final Duration DEFAULT_ACK_EXPIRATION_PADDING = Duration.millis(500); String subscription; Optional credentials; MessageReceiver receiver; Duration ackExpirationPadding; Optional maxOutstandingMessages; Optional maxOutstandingBytes; Optional executor; Optional channel; /** * Constructs a new {@link Builder}. * *

Once {@link #build()} is called a gRPC stub will be created for use of the {@link * Publisher}. * * @param subscription Cloud Pub/Sub subscription to bind the subscriber to * @param receiver an implementation of {@link MessageReceiver} used to process the received * messages */ public static Builder newBuilder(String subscription, MessageReceiver receiver) { return new Builder(subscription, receiver); } Builder(String subscription, MessageReceiver receiver) { setDefaults(); this.subscription = subscription; this.receiver = receiver; } private void setDefaults() { credentials = Optional.absent(); channel = Optional.absent(); ackExpirationPadding = DEFAULT_ACK_EXPIRATION_PADDING; maxOutstandingBytes = Optional.absent(); maxOutstandingMessages = Optional.absent(); executor = Optional.absent(); } /** * Credentials to authenticate with. * *

Must be properly scoped for accessing Cloud Pub/Sub APIs. */ public Builder setCredentials(Credentials credentials) { this.credentials = Optional.of(Preconditions.checkNotNull(credentials)); return this; } /** * Channel to use. * *

Must point at Cloud Pub/Sub endpoint. */ public Builder setChannel(Channel channel) { this.channel = Optional.of(Preconditions.checkNotNull(channel)); return this; } /** * Sets the maximum number of outstanding messages; messages delivered to the {@link * MessageReceiver} that have not been acknowledged or rejected. * * @param maxOutstandingMessages must be greater than 0 */ public void setMaxOutstandingMessages(int maxOutstandingMessages) { Preconditions.checkArgument( maxOutstandingMessages > 0, "maxOutstandingMessages limit is disabled by default, but if set it must be set to a " + "value greater to 0."); this.maxOutstandingMessages = Optional.of(maxOutstandingMessages); } /** * Sets the maximum number of outstanding bytes; bytes delivered to the {@link MessageReceiver} * that have not been acknowledged or rejected. * * @param maxOutstandingBytes must be greater than 0 */ public void setMaxOutstandingBytes(int maxOutstandingBytes) { Preconditions.checkArgument( maxOutstandingBytes > 0, "maxOutstandingBytes limit is disabled by default, but if set it must be set to a value " + "greater than 0."); this.maxOutstandingBytes = Optional.of(maxOutstandingBytes); } /** * Set acknowledgement expiration padding. * *

This is the time accounted before a message expiration is to happen, so the * {@link Subscriber} is able to send an ack extension beforehand. * *

This padding duration is configurable so you can account for network latency. A reasonable * number must be provided so messages don't expire because of network latency between when the * ack extension is required and when it reaches the Pub/Sub service. * * @param ackExpirationPadding must be greater or equal to {@link #MIN_ACK_EXPIRATION_PADDING} */ public void setAckExpirationPadding(Duration ackExpirationPadding) { Preconditions.checkArgument(ackExpirationPadding.compareTo(MIN_ACK_EXPIRATION_PADDING) >= 0); this.ackExpirationPadding = ackExpirationPadding; } /** Gives the ability to set a custom executor. */ public void setExecutor(ScheduledExecutorService executor) { this.executor = Optional.of(executor); } public Subscriber build() { return new SubscriberImpl(this); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy