com.alibaba.nacos.api.remote.DefaultRequestFuture Maven / Gradle / Ivy
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* 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.alibaba.nacos.api.remote;
import com.alibaba.nacos.api.remote.response.Response;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* default request future.
*
* @author liuzunfei
* @version $Id: DefaultRequestFuture.java, v 0.1 2020年09月01日 6:42 PM liuzunfei Exp $
*/
public class DefaultRequestFuture implements RequestFuture {
private long timeStamp;
private volatile boolean isDone = false;
private boolean isSuccess;
private RequestCallBack requestCallBack;
private Exception exception;
private String requestId;
private String connectionId;
private Response response;
private ScheduledFuture timeoutFuture;
TimeoutInnerTrigger timeoutInnerTrigger;
/**
* Getter method for property requestCallBack.
*
* @return property value of requestCallBack
*/
public RequestCallBack getRequestCallBack() {
return requestCallBack;
}
/**
* Getter method for property timeStamp.
*
* @return property value of timeStamp
*/
public long getTimeStamp() {
return timeStamp;
}
public DefaultRequestFuture(String connectionId, String requestId) {
this(connectionId, requestId, null, null);
}
public DefaultRequestFuture(String connectionId, String requestId, RequestCallBack requestCallBack,
TimeoutInnerTrigger timeoutInnerTrigger) {
this.timeStamp = System.currentTimeMillis();
this.requestCallBack = requestCallBack;
this.requestId = requestId;
this.connectionId = connectionId;
if (requestCallBack != null) {
this.timeoutFuture = RpcScheduledExecutor.TIMEOUT_SCHEDULER
.schedule(new TimeoutHandler(), requestCallBack.getTimeout(), TimeUnit.MILLISECONDS);
}
this.timeoutInnerTrigger = timeoutInnerTrigger;
}
public void setResponse(final Response response) {
isDone = true;
this.response = response;
this.isSuccess = response.isSuccess();
if (this.timeoutFuture != null) {
timeoutFuture.cancel(true);
}
synchronized (this) {
notifyAll();
}
callBacInvoke();
}
public void setFailResult(Exception e) {
isDone = true;
isSuccess = false;
this.exception = e;
synchronized (this) {
notifyAll();
}
callBacInvoke();
}
private void callBacInvoke() {
if (requestCallBack != null) {
if (requestCallBack.getExecutor() != null) {
requestCallBack.getExecutor().execute(new CallBackHandler());
} else {
new CallBackHandler().run();
}
}
}
public String getRequestId() {
return this.requestId;
}
@Override
public boolean isDone() {
return isDone;
}
@Override
public Response get() throws InterruptedException {
synchronized (this) {
while (!isDone) {
wait();
}
}
return response;
}
@Override
public Response get(long timeout) throws TimeoutException, InterruptedException {
if (timeout < 0) {
synchronized (this) {
while (!isDone) {
wait();
}
}
} else if (timeout > 0) {
long end = System.currentTimeMillis() + timeout;
long waitTime = timeout;
synchronized (this) {
while (!isDone && waitTime > 0) {
wait(waitTime);
waitTime = end - System.currentTimeMillis();
}
}
}
if (isDone) {
return response;
} else {
if (timeoutInnerTrigger != null) {
timeoutInnerTrigger.triggerOnTimeout();
}
throw new TimeoutException(
"request timeout after " + timeout + " milliseconds, requestId=" + requestId + ", connectionId="
+ connectionId);
}
}
class CallBackHandler implements Runnable {
@Override
public void run() {
if (exception != null) {
requestCallBack.onException(exception);
} else {
requestCallBack.onResponse(response);
}
}
}
class TimeoutHandler implements Runnable {
public TimeoutHandler() {
}
@Override
public void run() {
setFailResult(new TimeoutException(
"Timeout After " + requestCallBack.getTimeout() + " milliseconds, requestId=" + requestId
+ ", connectionId=" + connectionId));
if (timeoutInnerTrigger != null) {
timeoutInnerTrigger.triggerOnTimeout();
}
}
}
public interface TimeoutInnerTrigger {
/**
* triggered on timeout .
*/
void triggerOnTimeout();
}
/**
* Getter method for property connectionId.
*
* @return property value of connectionId
*/
public String getConnectionId() {
return connectionId;
}
}