diff --git a/README.md b/README.md index 6874bf8..f01e595 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,103 @@ abutil is a collection of often-used Golang helpers. -## Usage +## Contents +- [Functions](#functions) + - [OnSignal](#onsignal) + - [Parallel](#parallel) + - [RollbackErr](#rollbackerr) + - [RemoteIP](#remoteip) + - [GracefulServer](#gracefulserver) +- [License](#license) -Please read the [Godoc](https://godoc.org/github.com/bahlo/abutil) for -an overview of the provided functionality and examples. +## Functions + +#### [OnSignal](https://godoc.org/github.com/bahlo/abutil#OnSignal) +Listens to various signals and executes the given function with the received +signal. + +```go +go abutil.OnSignal(func(s os.Signal) { + fmt.Printf("Got signal %s\n", s) +}) +``` + +#### [Parallel](https://godoc.org/github.com/bahlo/abutil#Parallel) +Executes the given function n times concurrently. + +```go +var m sync.Mutex +c := 0 +abutil.Parallel(4, func() { + m.Lock() + defer m.Unlock() + + fmt.Print(c) + c++ +}) +``` + +#### [RollbackErr](https://godoc.org/github.com/bahlo/abutil#RollbackErr) +Does a rollback on the given transaction and returns either the rollback-error, +if occured, or the given one. + +```go +insertSomething := func(db *sql.DB) error { + tx, _ := db.Begin() + + _, err := tx.Exec("INSERT INTO some_table (some_column) VALUES (?)", + "foobar") + if err != nil { + // The old way, imagine doing this 10 times in a method + if err := tx.Rollback(); err != nil { + return err + } + + return err + } + + _, err = tx.Exec("DROP DATABASE foobar") + if err != nil { + // With RollbackErr + return abutil.RollbackErr(tx, err) + } + + return nil +} +``` + +#### [RemoteIP](https://godoc.org/github.com/bahlo/abutil#RemoteIP) +Tries everything to get the remote ip. + +```go +someHandler := func(w http.ResponseWriter, r *http.Request) { + fmt.Printf("New request from %s\n", abutil.RemoteIP(r)) +} +``` + +#### [GracefulServer](https://godoc.org/github.com/bahlo/abutil#GracefulServer) +A wrapper around `graceful.Server` from +with state variable and easier handling. + +```go +s := abutil.NewGracefulServer(1337, someHandlerFunc) + +// This channel blocks until all connections are closed or the time is up +sc := s.StopChan() + +// Some go func that stops the server after 2 seconds for no reason +time.After(2 * time.Second, func() { + s.Stop(10 * time.Second) +}) + +if err := s.ListenAndServe(); err != nil && !s.Stopped() { + // We didn't stop the server, so something must be wrong + panic(err) +} + +// Wait for the server to finish +<-sc +``` ## License diff --git a/concurrency_test.go b/concurrency_test.go index 2a3134b..3eddc6b 100644 --- a/concurrency_test.go +++ b/concurrency_test.go @@ -15,11 +15,12 @@ func TestParallel(t *testing.T) { wg.Add(2) go Parallel(2, func() { m.Lock() + defer func() { + m.Unlock() + wg.Done() + }() counter++ - - m.Unlock() - wg.Done() }) wg.Wait() @@ -35,11 +36,10 @@ func ExampleParallel() { c := 0 Parallel(4, func() { m.Lock() + defer m.Unlock() fmt.Print(c) c++ - - m.Unlock() }) // Output: 0123 diff --git a/database_test.go b/database_test.go index a745c07..1ec0812 100644 --- a/database_test.go +++ b/database_test.go @@ -70,13 +70,17 @@ func ExampleRollbackErr() { _, err := tx.Exec("INSERT INTO some_table (some_column) VALUES (?)", "foobar") if err != nil { - // We now have a one-liner instead of a check every time an error - // occurs - return RollbackErr(tx, err) + // The old way, imagine doing this 10 times in a method + if err := tx.Rollback(); err != nil { + return err + } + + return err } _, err = tx.Exec("DROP DATABASE foobar") if err != nil { + // With RollbackErr return RollbackErr(tx, err) } diff --git a/http_test.go b/http_test.go index 47ea440..679aeb5 100644 --- a/http_test.go +++ b/http_test.go @@ -184,16 +184,22 @@ func ExampleGracefulServer() { w.Write([]byte("Foo bar")) })) - time.AfterFunc(20*time.Millisecond, func() { - // For some reason, we need to stop + // This channel blocks until all connections are closed or the time is up + sc := s.StopChan() + + // Some go func that stops the server after 2 seconds for no reason + time.AfterFunc(1*time.Second, func() { fmt.Print("Stopping server..") - s.Stop(0) + s.Stop(10 * time.Second) }) if err := s.ListenAndServe(); err != nil && !s.Stopped() { - // An error occured but it wasn't intentionally + // We didn't stop the server, so something must be wrong panic(err) } + + // Wait for the server to finish + <-sc fmt.Print("bye!") // Output: Stopping server..bye!