public CompletableFuture<ChangeInvisibleDurationResponse> changeInvisibleDuration(ProxyContext ctx,
        ChangeInvisibleDurationRequest request) {
        CompletableFuture<ChangeInvisibleDurationResponse> future = new CompletableFuture<>();

        try {
            validateTopicAndConsumerGroup(request.getTopic(), request.getGroup());
            validateInvisibleTime(Durations.toMillis(request.getInvisibleDuration()));

            ReceiptHandle receiptHandle = ReceiptHandle.decode(request.getReceiptHandle());
            String group = request.getGroup().getName();

            MessageReceiptHandle messageReceiptHandle = messagingProcessor.removeReceiptHandle(ctx, grpcChannelManager.getChannel(ctx.getClientID()), group, request.getMessageId(), receiptHandle.getReceiptHandle());
            if (messageReceiptHandle != null) {
                receiptHandle = ReceiptHandle.decode(messageReceiptHandle.getReceiptHandleStr());
            }
            return this.messagingProcessor.changeInvisibleTime(
                ctx,
                receiptHandle,
                request.getMessageId(),
                group,
                request.getTopic().getName(),
                Durations.toMillis(request.getInvisibleDuration())
            ).thenApply(ackResult -> convertToChangeInvisibleDurationResponse(ctx, request, ackResult));
        } catch (Throwable t) {
            future.completeExceptionally(t);
        }
        return future;
    }
@Test
    public void testChangeInvisibleDurationActivityWhenHasMappingHandle() throws Throwable {
        String newHandle = "newHandle";
        ArgumentCaptor<Long> invisibleTimeArgumentCaptor = ArgumentCaptor.forClass(Long.class);
        AckResult ackResult = new AckResult();
        ackResult.setExtraInfo(newHandle);
        ackResult.setStatus(AckStatus.OK);
        String savedHandleStr = buildReceiptHandle("topic", System.currentTimeMillis(),3000);
        ArgumentCaptor<ReceiptHandle> receiptHandleCaptor = ArgumentCaptor.forClass(ReceiptHandle.class);
        when(this.messagingProcessor.changeInvisibleTime(
            any(), receiptHandleCaptor.capture(), anyString(), anyString(), anyString(), invisibleTimeArgumentCaptor.capture()
        )).thenReturn(CompletableFuture.completedFuture(ackResult));
        when(messagingProcessor.removeReceiptHandle(any(), any(), anyString(), anyString(), anyString()))
            .thenReturn(new MessageReceiptHandle("group", "topic", 0, savedHandleStr, "msgId", 0, 0));

        ChangeInvisibleDurationResponse response = this.changeInvisibleDurationActivity.changeInvisibleDuration(
            createContext(),
            ChangeInvisibleDurationRequest.newBuilder()
                .setInvisibleDuration(Durations.fromSeconds(3))
                .setTopic(Resource.newBuilder().setName(TOPIC).build())
                .setGroup(Resource.newBuilder().setName(CONSUMER_GROUP).build())
                .setMessageId("msgId")
                .setReceiptHandle(buildReceiptHandle(TOPIC, System.currentTimeMillis(), 3000))
                .build()
        ).get();

        assertEquals(Code.OK, response.getStatus().getCode());
        assertEquals(TimeUnit.SECONDS.toMillis(3), invisibleTimeArgumentCaptor.getValue().longValue());
        assertEquals(savedHandleStr, receiptHandleCaptor.getValue().getReceiptHandle());
        assertEquals(newHandle, response.getReceiptHandle());
    }