Browse Source
feat: 支持beforePublishHook, afterPublishHook回调. feat: publishWithReply提供CompletableFuture支持.pull/42/head
Vincent
1 year ago
11 changed files with 475 additions and 7 deletions
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.Chan; |
||||
import com.dji.sdk.mqtt.CommonTopicRequest; |
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
|
||||
import java.util.Objects; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
public class JDKLockBarrierImpl implements PublishBarrier{ |
||||
|
||||
/** |
||||
* 在我的实现中是采用一个定期清理的TimedCache储存请求 |
||||
*/ |
||||
private final ConcurrentHashMap<String, JDKHolder> container = new ConcurrentHashMap<>(); |
||||
|
||||
@Override |
||||
public void put(String identity, CommonTopicResponse receiveData) { |
||||
if(hasIdentity(identity)){ |
||||
container.get(identity).setData(receiveData); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void registerRequest(String identity, CommonTopicRequest requestData) { |
||||
container.put(identity,new JDKHolder()); |
||||
} |
||||
|
||||
@Override |
||||
public PublishBarrierResult await(String identity, long timeout) { |
||||
JDKHolder jdkHolder = container.get(identity); |
||||
if(Objects.isNull(jdkHolder)){ |
||||
throw new RuntimeException("等待指令返回前未注册指令到栅栏"); |
||||
} |
||||
jdkHolder.await(timeout); |
||||
|
||||
return jdkHolder.getResult(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasIdentity(String identity) { |
||||
return container.containsKey(identity); |
||||
} |
||||
|
||||
public static class JDKHolder{ |
||||
volatile Object locker = new Object(); |
||||
CommonTopicResponse response = null; |
||||
|
||||
public void await(long timeout) { |
||||
synchronized (locker){ |
||||
try { |
||||
locker.wait(timeout); |
||||
}catch (InterruptedException e){} |
||||
} |
||||
} |
||||
|
||||
public void setData(CommonTopicResponse receiveData) { |
||||
this.response = receiveData; |
||||
synchronized (locker){ |
||||
locker.notify(); |
||||
} |
||||
} |
||||
|
||||
public PublishBarrierResult getResult() { |
||||
if(Objects.nonNull(response)){ |
||||
return PublishBarrierResult.ok(response); |
||||
}else{ |
||||
return PublishBarrierResult.EMPTY; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.CommonTopicRequest; |
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
|
||||
public interface PublishBarrier { |
||||
|
||||
void put(String identity, CommonTopicResponse receiveData); |
||||
|
||||
void registerRequest(String identity, CommonTopicRequest requestData); |
||||
|
||||
PublishBarrierResult await(String identity,long timeout); |
||||
|
||||
boolean hasIdentity(String identity); |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
|
||||
public class PublishBarrierResult { |
||||
|
||||
public static PublishBarrierResult EMPTY = new PublishBarrierResult(); |
||||
|
||||
public static PublishBarrierResult ok(CommonTopicResponse data){ |
||||
return new PublishBarrierResult().setData(data); |
||||
} |
||||
|
||||
|
||||
boolean timeout = true; |
||||
|
||||
CommonTopicResponse data; |
||||
|
||||
private PublishBarrierResult() { |
||||
} |
||||
|
||||
private PublishBarrierResult setData(CommonTopicResponse data) { |
||||
this.data = data; |
||||
this.timeout = false; |
||||
return this; |
||||
} |
||||
|
||||
public boolean isTimeout(){ |
||||
return timeout; |
||||
} |
||||
|
||||
public <T> CommonTopicResponse<T> getData(){ |
||||
return data; |
||||
} |
||||
} |
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.CommonTopicRequest; |
||||
|
||||
import java.util.Objects; |
||||
import java.util.function.BiConsumer; |
||||
import java.util.function.Consumer; |
||||
|
||||
public class PublishConfiguration { |
||||
|
||||
String bid; |
||||
String tid; |
||||
|
||||
//默认超时
|
||||
int timeout = 3; |
||||
//请求发送前调用
|
||||
Consumer<CommonTopicRequest> beforePublishHook = (e)->{}; |
||||
//收到请求回信后调用
|
||||
BiConsumer<CommonTopicRequest, PublishBarrierResult> afterPublishHook = (req,rsp) ->{}; |
||||
|
||||
|
||||
public String getBid() { |
||||
return bid; |
||||
} |
||||
|
||||
public String getTid() { |
||||
return tid; |
||||
} |
||||
|
||||
public long getTimeout() { |
||||
return timeout * 1000; |
||||
} |
||||
|
||||
public void setBizId(String bid) { |
||||
this.bid = bid; |
||||
} |
||||
|
||||
public void setTransactionId(String tid) { |
||||
this.tid = tid; |
||||
} |
||||
|
||||
public void setTimeout(int timeout) { |
||||
this.timeout = timeout; |
||||
} |
||||
|
||||
public void setBeforePublishHook(Consumer<CommonTopicRequest> callback) { |
||||
beforePublishHook = callback; |
||||
} |
||||
|
||||
public void setAfterPublishReplyHook(BiConsumer<CommonTopicRequest, PublishBarrierResult> callback) { |
||||
afterPublishHook = callback; |
||||
} |
||||
|
||||
public void invokeBeforePublishHook(CommonTopicRequest req){ |
||||
if(Objects.nonNull(beforePublishHook)){ |
||||
try { |
||||
beforePublishHook.accept(req); |
||||
}catch (Throwable ex){ |
||||
//do nothing
|
||||
//业务层的异常不理会
|
||||
} |
||||
} |
||||
} |
||||
|
||||
public void invokeAfterPublishReplyHook(CommonTopicRequest req, PublishBarrierResult result){ |
||||
if(Objects.nonNull(afterPublishHook)){ |
||||
try{ |
||||
afterPublishHook.accept(req,result); |
||||
}catch (Throwable ex){ |
||||
//do nothing
|
||||
//业务层的异常不理会
|
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.CommonTopicRequest; |
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
import com.google.common.base.Strings; |
||||
|
||||
import java.util.Objects; |
||||
import java.util.function.BiConsumer; |
||||
import java.util.function.Consumer; |
||||
|
||||
public class PublishOption { |
||||
|
||||
public static Consumer<PublishOption> DEFAULT = (cfg)->{}; |
||||
|
||||
final PublishConfiguration configuration; |
||||
|
||||
public PublishOption(PublishConfiguration configuration) { |
||||
this.configuration = configuration; |
||||
} |
||||
|
||||
public PublishOption withBizId(String bid){ |
||||
if(!Strings.isNullOrEmpty(bid)){ |
||||
configuration.setBizId(bid); |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
public PublishOption withTransactionId(String tid){ |
||||
if(!Strings.isNullOrEmpty(tid)){ |
||||
configuration.setTransactionId(tid); |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
public PublishOption timeout(int second){ |
||||
configuration.setTimeout(second); |
||||
return this; |
||||
} |
||||
|
||||
public PublishOption beforePublish(Consumer<CommonTopicRequest> callback){ |
||||
if(Objects.nonNull(callback)){ |
||||
configuration.setBeforePublishHook(callback); |
||||
} |
||||
return this; |
||||
} |
||||
public PublishOption afterPublishReply(BiConsumer<CommonTopicRequest, PublishBarrierResult> callback){ |
||||
if(Objects.nonNull(callback)){ |
||||
configuration.setAfterPublishReplyHook(callback); |
||||
} |
||||
return this; |
||||
} |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.config; |
||||
|
||||
import com.dji.sdk.common.JDKLockBarrierImpl; |
||||
import com.dji.sdk.common.PublishBarrier; |
||||
import com.dji.sdk.mqtt.ChanBarrierAdapter; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
@Configuration |
||||
public class DefaultBeanConfiguration { |
||||
|
||||
/** |
||||
* 使用者可以自定义PublishBarrier的实现,默认采用Chan实现 |
||||
*/ |
||||
@Bean |
||||
@ConditionalOnMissingBean(PublishBarrier.class) |
||||
public PublishBarrier chanBarrier(){ |
||||
/** 原Chan实现 */ |
||||
return new ChanBarrierAdapter(); |
||||
} |
||||
|
||||
/** |
||||
* PublishBarrier 另一个实现, 采用同步锁 |
||||
*/ |
||||
// @Bean
|
||||
// @ConditionalOnMissingBean(PublishBarrier.class)
|
||||
// public PublishBarrier jdkBarrier(){
|
||||
// return new JDKLockBarrierImpl();
|
||||
// }
|
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.mqtt; |
||||
|
||||
import com.dji.sdk.common.PublishBarrier; |
||||
import com.dji.sdk.common.PublishBarrierResult; |
||||
|
||||
import java.util.Objects; |
||||
|
||||
public class ChanBarrierAdapter implements PublishBarrier { |
||||
@Override |
||||
public void put(String identity, CommonTopicResponse receiveData) { |
||||
Chan instance = Chan.getInstance(identity, false); |
||||
if(Objects.nonNull(instance)){ |
||||
instance.put(receiveData); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void registerRequest(String identity, CommonTopicRequest requestData) { |
||||
Chan.getInstance(identity, true); |
||||
} |
||||
|
||||
@Override |
||||
public PublishBarrierResult await(String identity,long timeout) { |
||||
Chan instance = Chan.getInstance(identity, false); |
||||
|
||||
CommonTopicResponse response = instance.get(identity, timeout); |
||||
|
||||
return Objects.nonNull(response) ? PublishBarrierResult.ok(response) : PublishBarrierResult.EMPTY; |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasIdentity(String identity) { |
||||
Chan instance = Chan.getInstance(identity, false); |
||||
return Objects.nonNull(instance); |
||||
} |
||||
} |
Loading…
Reference in new issue