package dev.elaine.network;

import java.time.Duration;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public final class MiniRpcSample {
    private final Map<String, CompletableFuture<Response>> pending = new ConcurrentHashMap<>();

    public record Request(String id, String service, String argument) {}
    public record Response(String id, String result, String error) {}

    public CompletableFuture<Response> call(String service, String argument, Duration timeout) {
        Request request = new Request(UUID.randomUUID().toString(), service, argument);
        CompletableFuture<Response> promise = new CompletableFuture<>();
        pending.put(request.id(), promise);
        CompletableFuture.runAsync(() -> receive(dispatch(request)));
        return promise.orTimeout(timeout.toMillis(), TimeUnit.MILLISECONDS)
                .whenComplete((ignored, error) -> pending.remove(request.id()));
    }

    private static Response dispatch(Request request) {
        if (!request.service().equals("greeting")) {
            return new Response(request.id(), null, "未知服务");
        }
        return new Response(request.id(), "你好，" + request.argument(), null);
    }

    private void receive(Response response) {
        CompletableFuture<Response> promise = pending.get(response.id());
        if (promise != null) {
            promise.complete(response);
        }
    }

    public static void main(String[] args) throws Exception {
        Response response = new MiniRpcSample()
                .call("greeting", "架构师", Duration.ofSeconds(1)).get();
        System.out.println(response.result());
    }
}

