Skip to content

samber/go-singleflightx

Repository files navigation

go-singleflightx

tag Go Version GoDoc Build Status Go report Coverage Contributors License

x/sync/singleflight but better

Features

This library is inspired by x/sync/singleflight but adds many features:

  • 🧬 generics
  • 🍱 batching: fetch multiple keys in a single callback, with in-flight deduplication
  • πŸ“­ nullable result
  • πŸ• sharded groups

πŸš€ Install

go get github.com/samber/go-singleflightx

This library is v0 and follows SemVer strictly. No breaking changes will be made to exported APIs before v1.0.0.

πŸ’‘ Doc

GoDoc: https://pkg.go.dev/github.com/samber/go-singleflightx

Examples

Here is an example of a user retrieval in a caching layer:

import "github.com/samber/go-singleflightx"

func getUsersByID(userIDs []string) (map[string]User, error) {
    users := []User{}

    // πŸ“ SQL query here...
    err := sqlx.Select(&users, "SELECT * FROM users WHERE id IN (?);", userIDs...)
    if err != nil {
        return nil, err
    }

    var results = map[string]User{}
    for _, u := range users {
        results[u.ID] = u
    }

    return results, nil
}

func main() {
    var g singleflightx.Group[string, User]

    // πŸ‘‡ concurrent queries will be dedup
    output := g.DoX([]string{"user-1", "user-2"}, getUsersByID)
}

output is of type map[K]singleflightx.Result[V], and will always have as many entries as requested, whatever the callback result.

type Result[V any] struct {
  	 Value  singleflightx.NullValue[V]  // πŸ’‘ A result is considered "null" if the callback did not return it.
  	 Err    error
  	 Shared bool
}

type NullValue[V any] struct {
	Value V
	Valid bool
}

Sharded groups, for high contention/concurrency environments

g := singleflightx.NewShardedGroup[K string, User](10, func (key string) uint {
    h := fnv.New64a()
    h.Write([]byte(key))
    return uint(h.Sum64())
})

// as usual, but if the keys match different shards, getUsersByID will be called twice
output := g.DoX([]string{"user-1", "user-2"}, getUsersByID) 

🀝 Contributing

Don't hesitate ;)

# Install some dev dependencies
make tools

# Run tests
make test
# or
make watch-test

πŸ‘€ Contributors

Contributors

πŸ’« Show your support

Give a ⭐️ if this project helped you!

GitHub Sponsors

πŸ“ License

Copyright Β© 2023 Samuel Berthe.

This project is MIT licensed.