import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;

/** Alur pemesanan yang sama pada dua gaya komunikasi: REST sinkron vs messaging asinkron. */
public class SinkronVsAsinkron {
    /** Satu langkah kerja: pelakunya, aksinya, dan bobot kerjanya. */
    record Pekerjaan(String pelaku, String aksi, int langkah) {}

    public static void main(String[] args) {
        System.out.println("== SINKRON: REST berantai, klien menunggu ==");
        List<Pekerjaan> rantai = List.of(
                new Pekerjaan("klien", "kirim POST ke svc-order", 0),
                new Pekerjaan("svc-order", "validasi pesanan", 1),
                new Pekerjaan("svc-pembayaran", "menagih kartu", 3),
                new Pekerjaan("svc-notifikasi", "menulis email", 2));

        int menungguSinkron = 0;
        for (Pekerjaan p : rantai) {
            System.out.println("  " + String.format("%-15s", p.pelaku()) + ": " + p.aksi()
                    + " (" + p.langkah() + " langkah)");
            menungguSinkron += p.langkah();
        }
        System.out.println("  -> klien dijawab setelah " + menungguSinkron + " langkah kerja");

        System.out.println();
        System.out.println("== ASINKRON: messaging lewat antrean ==");
        // svc-order memvalidasi, menjawab klien, lalu mempublikasikan satu event
        System.out.println("  svc-order     : validasi pesanan (1 langkah), menjawab klien");

        Deque<String> antrean = new ArrayDeque<>();
        antrean.offer("event PesananDibuat#1001");

        // Penerbit tidak tahu siapa pelanggannya; antrean yang menyebarkan
        List<String> pelanggan = List.of("svc-pembayaran", "svc-notifikasi");

        int kerjaBelakangan = 0;
        while (!antrean.isEmpty()) {
            String event = antrean.poll();
            for (String p : pelanggan) {
                int langkah = p.equals("svc-pembayaran") ? 3 : 2;
                kerjaBelakangan += langkah;
                System.out.println("  antrean -> " + String.format("%-15s", p) + ": "
                        + event + " diproses (" + langkah + " langkah, klien tidak menunggu)");
            }
        }
        System.out.println("  -> klien dijawab setelah 1 langkah; "
                + kerjaBelakangan + " langkah berjalan setelah jawaban terkirim");
    }
}
