简体   繁体   中英

How to stop and start a PubSub programatically through the MessageReceiver in Java

is it possible to pause and start a GCP PubSub Subscriber(pull) programatically using Java?

I have the following code for the MessageReceiver:

MessageReceiver receiver = (message, consumer) -> {
            System.out.println("Received message: " + message.getData().toStringUtf8() + " at " + LocalDateTime.now());

            Mono<Void> mono = Mono.just(message.getData().toStringUtf8())
                    .flatMap(deserializePayload())
                    .doOnSuccess(creditNoteRequestDTO -> configureMDC(message.getAttributesMap(), creditNoteRequestDTO.getOrderNumber()))
                    .doOnError(error -> log.error("Problem while parsing CreditNoteRequest DTO {}", message.getData().toStringUtf8(), error))
                    .map(creditNoteRequestMapper::mapToCreditNoteRequest)
                    .flatMap(creditNoteRequestProcess::process)
                    .doOnError(throwable -> {
                        if (throwable instanceof CallNotPermittedException) ConstantUtils.ENABLED_SUBSCRIBER = false;
                        consumer.nack();
                    })
                    .doOnSuccess(unused -> {
                        log.info("Doing ACK on payload {}", message.getData().toStringUtf8());
                        consumer.ack();
                    });

            if (Boolean.TRUE.equals(ConstantUtils.ENABLED_SUBSCRIBER)) {
                mono.subscribe();
            } else {
                System.err.println("Subscription has been disabled.");
                //mono.subscribe().dispose();
                try {
                    System.err.println("PRE: " + LocalDateTime.now() + " " + ConstantUtils.ENABLED_SUBSCRIBER);
                    TimeUnit.SECONDS.sleep(15);
                    ConstantUtils.ENABLED_SUBSCRIBER = true;
                    System.err.println("POST: " + LocalDateTime.now() + " " + ConstantUtils.ENABLED_SUBSCRIBER);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        };

And the following for the subscriber:

Subscriber subscriber = null;
        FlowControlSettings controlSettings = FlowControlSettings
                .newBuilder()
                .setMaxOutstandingElementCount(2000L)
                .build();

        subscriber = Subscriber
                .newBuilder(subscription, receiver)
                .setFlowControlSettings(controlSettings)
                .build();

        // Start the subscriber.
        subscriber.startAsync().awaitRunning();
        System.out.printf("Listening for messages on %s:\n", subscription);
        System.out.printf("Max elements count: %s\n", subscriber.getFlowControlSettings().getMaxOutstandingElementCount());
        // Allow the subscriber to run for 45s unless an unrecoverable error occurs.

        Subscriber finalSubscriber = subscriber;
        new java.util.Timer().schedule(
                new java.util.TimerTask() {
                    @Override
                    public void run() {
                        System.err.println("Subscriber has been shut down.");
                        finalSubscriber.stopAsync();
                    }
                },
                120000
        );

It is somehow possible to use finalSubscriber.stopAsync(); on the MessageReceiver or pause the messageReceiver?

UPDATE: Thanks, i managed to stop it, but how do i restart it now, when i try to restart, nothing happens.

private void createSubscriber() {
        ProjectSubscriptionName subscription = ProjectSubscriptionName.of("txd-boss-dev", "circuit-breaker-test-sub");
        this.subscriber = Subscriber.newBuilder(subscription, getMessageReceiver()).build();
    }

    private void runSubscriber(boolean start) {
        if(start) {

            try {
                this.subscriber.startAsync().awaitRunning();
                System.out.printf("Listening for messages on %s:\n", this.subscriber.getSubscriptionNameString());
                subscriber.awaitTerminated(240, TimeUnit.SECONDS);
            } catch (TimeoutException e) {
                System.err.println("Shutting down subscription.");
                runSubscriber(false);
            }

        } else {
            subscriber.stopAsync();
        }
    }

    @EventListener(ContextRefreshedEvent.class)
    public void test() {
        createSubscriber();
        runSubscriber(true);
    }

You need to return the same subscriber object to start and stop it:

check some google examples here .

here is a sketch (adapt for your class) :

private Subscriber StartSubscriber() {

    Subscriber subscriber = null;
    try {
        subscriber = Subscriber.newBuilder(subscriptionName, receiver).build();
        subscriber.startAsync().awaitRunning();
        System.out.printf("Listening for messages on %s:\n", subscriptionName.toString());
        subscriber.awaitTerminated(30, TimeUnit.SECONDS);
        return subscriber;
    } catch (TimeoutException timeoutException) {
        // Shut down the subscriber after 30s. Stop receiving messages.
        System.out.printf("Error \n");
        subscriber.stopAsync();
    }

}

private void StopSubscriber(Subscriber subscriber) {

    System.out.printf("Stoping subscriber\n");
    subscriber.stopAsync();
}


public void test() {
    Subscriber subscriber = StartSubscriber();
    StopSubscriber(subscriber);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM