package main

import (
	"context"
	"fmt"
	"time"
)

// QueryLambat meniru query database yang membutuhkan 50 milidetik.
// Fungsi ini menghormati context: bila ctx dibatalkan lebih dulu,
// fungsi langsung kembali tanpa menunggu kerja selesai.
func QueryLambat(ctx context.Context) (string, error) {
	selesai := make(chan string, 1)
	go func() {
		time.Sleep(50 * time.Millisecond) // kerja tiruan query berat
		selesai <- "42 baris"
	}()

	select {
	case hasil := <-selesai:
		return hasil, nil
	case <-ctx.Done():
		return "", ctx.Err() // context.DeadlineExceeded
	}
}

func main() {
	// Skenario 1: batas waktu 200 ms, query 50 ms selesai lebih dulu.
	ctxLonggar, batal1 := context.WithTimeout(context.Background(), 200*time.Millisecond)
	defer batal1()
	hasil, err := QueryLambat(ctxLonggar)
	fmt.Printf("batas 200ms: hasil=%q err=%v\n", hasil, err)

	// Skenario 2: batas waktu 10 ms, query dibatalkan di tengah jalan.
	ctxKetat, batal2 := context.WithTimeout(context.Background(), 10*time.Millisecond)
	defer batal2()
	hasil2, err2 := QueryLambat(ctxKetat)
	fmt.Printf("batas 10ms : hasil=%q err=%v\n", hasil2, err2)
}
