Skip to content

Instantly share code, notes, and snippets.

@jccatrinck
Created June 18, 2023 18:21
Show Gist options
  • Save jccatrinck/9b5c02cfb8c9420431def6b44986c2ec to your computer and use it in GitHub Desktop.
Save jccatrinck/9b5c02cfb8c9420431def6b44986c2ec to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"log"
"net/http"
"strconv"
"sync/atomic"
"time"
)
type processMsg struct {
person Person
chResult chan error
}
type Person struct {
Name string
Age int
}
const (
maxConcurrentProcesses = 50
)
var (
chProcesses = make(chan processMsg, maxConcurrentProcesses)
currentRunning int32
)
func getCurrentRunning() int32 {
return atomic.LoadInt32(&currentRunning)
}
func addCurrentRunning(amount int32) {
atomic.StoreInt32(&currentRunning, atomic.LoadInt32(&currentRunning)+amount)
}
func init() {
go func() {
chControl := make(chan struct{}, maxConcurrentProcesses)
for {
msg := <-chProcesses
chControl <- struct{}{}
go func() {
process(msg.person)
msg.chResult <- nil
<-chControl
}()
}
}()
}
func queueProcess(person Person) error {
ch := make(chan error)
chProcesses <- processMsg{
person: person,
chResult: ch,
}
return <-ch
}
func process(p Person) {
addCurrentRunning(1)
fmt.Printf("goroutines: %v of %v\n", getCurrentRunning(), maxConcurrentProcesses)
time.Sleep(5 * time.Second)
fmt.Printf("Complete person: %+v:\n", p)
addCurrentRunning(-1)
fmt.Printf("removed goroutine %v\n", getCurrentRunning())
}
func main() {
http.HandleFunc("/", handlerFunc)
if err := http.ListenAndServe(":9000", nil); err != nil {
log.Panic(err)
}
}
func handlerFunc(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(405)
return
}
start := time.Now()
value, err := strconv.Atoi(r.FormValue("value"))
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, "should pass params value with value to process")
return
}
name := r.FormValue("name")
if len(name) == 0 {
w.WriteHeader(500)
fmt.Fprint(w, "should pass params name")
return
}
person := Person{
Name: name,
Age: value,
}
err = queueProcess(person)
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, "error when processing")
return
}
w.WriteHeader(201)
fmt.Fprintf(w, "Time used to process %v is %vs", value, time.Since(start).Seconds())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment