Solon v3.6.0

dami - 定制“荷载”(payload)

</> markdown

1、使用定制“荷载”(payload)

此处借用框架内置的一个 “荷载” ReceivablePayload (一个普通的实体类),发送可以再接收响应。

public class ReceivablePayload<D,Rec> {
    private final D data;
    private final transient Rec sink;

    public ReceivablePayload(D data, Rec sink) {
        AssertUtil.notNull(sink, "The sink can not be null");

        this.data = data;
        this.sink = sink;
    }

    public D getData() {  return data; }
    public Rec getSink() {   return sink; }
}

应用示例:

public class DemoApp {
    static String topic = "demo.hello";

    public static void main(String[] args) throws Exception {
        //监听事件
        Dami.bus().<ReceivablePayload<String, CompletableFuture<String>>>listen(topic, event -> {
            System.err.println(event.getPayload().getData());
            event.getPayload().getSink().complete("me to!");
        });

        //发送事件
        String rst = Dami.bus().<ReceivablePayload<String, CompletableFuture<String>>>send(topic, new ReceivablePayload<>("{name:'noear',say:'hello'}", new CompletableFuture<>()))
                .getPayload()
                .getReceiver()
                .get();
        System.out.println(rst);
    }
}

2、定制的演化

ReceivablePayload 提供了交互基础,但直接使用需要大串的泛型声明。下面使用另一个定制 “荷载” CallPayload,指定了 “接收器” 为 CompletableFuture,这样会简化些:

public class CallPayload<D,R> extends ReceivablePayload<D, CompletableFuture<R>> {
    public CallPayload(D data) {
        super(data, new CompletableFuture<>());
    }

    @Override
    public CompletableFuture<R> getSink() { return super.getSink(); }
}

应用演进示例:

public class DemoApp {
    static String topic = "demo.hello";

    public static void main(String[] args) throws Exception {
        //监听事件
        Dami.bus().<CallPayload<String, String>>listen(topic, event -> {
            System.err.println(event.getPayload().getData());
            event.getPayload().getSink().complete("me to!");
        });

        //发送事件
        String rst = Dami.bus().<CallPayload<String, String>>send(topic, new CallPayload<>("{name:'noear',say:'hello'}"))
                .getPayload()
                .getReceiver()
                .get();
        System.out.println(rst);
    }
}

从框架的角度 “请求/响应” 这种模式是常见的存在。需要提供更简洁的体验。所以专门定制了简化接口:

public class DemoApp {
    static String topic = "demo.hello";

    public static void main(String[] args) throws Exception {
        //监听事件
        Dami.bus().<String, String>listen(topic, (event, content, receiver) -> {
            System.err.println(content);
            receiver.complete("me to!");
        });

        //发送事件
        String rst = Dami.bus().<String, String>call(topic, "{name:'noear',say:'hello'}").get();
        System.out.println(rst);
    }
}

3、演化的终点,定制空接口(定制的过程,主要是固化泛型)

上面的杂乱主要是因为泛型的声明。下面以实现 call 效果为例,定制一个 DamiCall (名字随便取的)接口。

public interface DamiCall {
    static DamiBus bus(){
        return Dami.bus();
    }
    
    //发送调用事件
    default <D, R> CompletableFuture<R> call(String topic, D data) {
        return call(topic, data, null);
    }

    //发送调用事件
    default <D, R> CompletableFuture<R> call(String topic, D data, Consumer<CompletableFuture<R>> fallback) {
        return callAsResult(topic, data, fallback).getPayload().getSink();
    }

    //发送调用事件
    default <D, R> Result<CallPayload<D, R>> callAsResult(String topic, D data) {
        return callAsResult(topic, data, null);
    }

    //发送调用事件
    default <D, R> Result<CallPayload<D, R>> callAsResult(String topic, D data, Consumer<CompletableFuture<R>> fallback) {
        if (fallback == null) {
            return bus().send(topic, new CallPayload<>(data));
        } else {
            return bus().send(topic, new CallPayload<>(data), r -> {
                fallback.accept(r.getSink());
            });
        }
    }

   //监听调用事件
    default <D, R> void listen(String topic, CallEventHandler<D, R> handler) {
        listen(topic, 0, handler);
    }

    //监听调用事件
    default <D, R> void listen(String topic, int index, CallEventHandler<D, R> handler) {
        bus().<CallPayload<D, R>>listen(topic, index, event -> {
            handler.onCall(event, event.getPayload().getData(), event.getPayload().getSink());
        });
    }
}

后续的应用效果:

public class DemoApp {
     public static void main(String[] args) throws Exception {
        DamiCall.<String,String>listen("demo.hello", (event, data, sink) -> {
            sink.complete("hello " + data);
        });
        
        DamiCall.<String,String>call("demo.hello", "world");
    }
}

也可以给 listen 换个名字,比如叫:onCall(和 call 形成一对)

public class DemoApp {
     public static void main(String[] args) throws Exception {
        DamiCall.<String,String>onCall("demo.hello", (event, data, sink) -> {
            sink.complete("hello " + data);
        });
        
        DamiCall.<String,String>call("demo.hello", "world");
    }
}