package main import ( "context" "encoding/json" "fmt" "log" "net/http" "time" _ "github.com/lib/pq" "tgs03-backend/config" "tgs03-backend/context_handler" "tgs03-backend/enrollment" "tgs03-backend/poll" "tgs03-backend/pool" "tgs03-backend/worker" ) func writeJSON(w http.ResponseWriter, v interface{}) { w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(v) } func main() { // initialize DB (attempt). If DB not reachable, still continue (some features simulate). db, err := config.InitDB() if err != nil { log.Printf("Warning: failed connect DB: %v (continuing in simulation mode)", err) } else { // keep db on global package defer db.Close() config.DB = db } // Initialize pool manager (simulated connections) pm := pool.NewDBManager(5) // capacity 5 // Initialize idempotency store enrollment.InitStore() mux := http.NewServeMux() // Endpoint: /sertifikasi -> run 50 goroutines with WaitGroup (Tugas 1.1) mux.HandleFunc("/sertifikasi", func(w http.ResponseWriter, r *http.Request) { n := 50 start := time.Now() results := worker.RunSertifikasi(n) duration := time.Since(start) writeJSON(w, map[string]interface{}{ "count": n, "duration": duration.String(), "results": results, }) }) // Endpoint: /pool -> run 20 goroutines that call EksekusiQuery (Tugas 1.2) mux.HandleFunc("/pool", func(w http.ResponseWriter, r *http.Request) { n := 20 // run queries concurrently res := pm.RunQueries(n) writeJSON(w, map[string]interface{}{ "requested": n, "results": res, }) }) // Endpoint: /poll -> worker pool 5 workers, send 100 jobs (Tugas 1.3) mux.HandleFunc("/poll", func(w http.ResponseWriter, r *http.Request) { jobCount := 100 workers := 5 results := poll.RunPollSimulation(workers, jobCount) writeJSON(w, map[string]interface{}{ "workers": workers, "job_count": jobCount, "results": results, }) }) // Endpoint: /context -> call FetchRiwayatKursus with 1s timeout (Tugas 2.1 & 2.2) mux.HandleFunc("/context", func(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*1) defer cancel() // attach user id ctx = context_handler.WithUserID(ctx, "REQ-456") start := time.Now() res, err := context_handler.FetchRiwayatKursus(ctx) duration := time.Since(start) if err != nil { writeJSON(w, map[string]interface{}{ "error": err.Error(), "duration": duration.String(), }) return } writeJSON(w, map[string]interface{}{ "duration": duration.String(), "data": res, }) }) // Endpoint: /enroll -> demonstrates idempotent enrollment (Tugas 2.3) // Query params: key (idempotency key). If omitted uses "idem-key-sample". mux.HandleFunc("/enroll", func(w http.ResponseWriter, r *http.Request) { key := r.URL.Query().Get("key") if key == "" { key = "idem-key-sample" } // run 5 goroutines concurrently with same key to demonstrate idempotency results := enrollment.RunConcurrentEnrollments(key, 5) writeJSON(w, results) }) addr := ":8080" fmt.Printf("Server running at %s\n", addr) log.Fatal(http.ListenAndServe(addr, mux)) }