hostpool.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // A Go package to intelligently and flexibly pool among multiple hosts from your Go application.
  2. // Host selection can operate in round robin or epsilon greedy mode, and unresponsive hosts are
  3. // avoided. A good overview of Epsilon Greedy is here http://stevehanov.ca/blog/index.php?id=132
  4. package hostpool
  5. import (
  6. "time"
  7. )
  8. // Returns current version
  9. func Version() string {
  10. return "0.1"
  11. }
  12. // --- Response interfaces and structs ----
  13. // This interface represents the response from HostPool. You can retrieve the
  14. // hostname by calling Host(), and after making a request to the host you should
  15. // call Mark with any error encountered, which will inform the HostPool issuing
  16. // the HostPoolResponse of what happened to the request and allow it to update.
  17. type HostPoolResponse interface {
  18. Host() string
  19. Mark(error)
  20. }
  21. type standardHostPoolResponse struct {
  22. host string
  23. ss *standardSelector
  24. }
  25. // --- HostPool structs and interfaces ----
  26. // This is the main HostPool interface. Structs implementing this interface
  27. // allow you to Get a HostPoolResponse (which includes a hostname to use),
  28. // get the list of all Hosts, and use ResetAll to reset state.
  29. type HostPool interface {
  30. Get() HostPoolResponse
  31. ResetAll()
  32. Hosts() []string
  33. }
  34. type standardHostPool struct {
  35. hosts []string
  36. Selector
  37. }
  38. // ------ constants -------------------
  39. const epsilonBuckets = 120
  40. const epsilonDecay = 0.90 // decay the exploration rate
  41. const minEpsilon = 0.01 // explore one percent of the time
  42. const initialEpsilon = 0.3
  43. const defaultDecayDuration = time.Duration(5) * time.Minute
  44. // Construct a basic HostPool using the hostnames provided
  45. func New(hosts []string) HostPool {
  46. return NewWithSelector(hosts, &standardSelector{})
  47. }
  48. func NewWithSelector(hosts []string, s Selector) HostPool {
  49. s.Init(hosts)
  50. return &standardHostPool{
  51. hosts,
  52. s,
  53. }
  54. }
  55. func (r *standardHostPoolResponse) Host() string {
  56. return r.host
  57. }
  58. func (r *standardHostPoolResponse) Mark(err error) {
  59. r.ss.MarkHost(r.host, err)
  60. }
  61. // return an entry from the HostPool
  62. func (p *standardHostPool) Get() HostPoolResponse {
  63. host := p.SelectNextHost()
  64. return p.MakeHostResponse(host)
  65. }
  66. func (p *standardHostPool) Hosts() []string {
  67. return p.hosts
  68. }