112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
package elasticsearch
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
// A Cluster is an actively-managed collection of Nodes. Cluster implements
|
|
// Searcher, so you can treat it as a single entity. Its Search method chooses
|
|
// the best Node to receive the Request.
|
|
type Cluster struct {
|
|
nodes Nodes
|
|
pingInterval time.Duration
|
|
shutdown chan chan bool
|
|
}
|
|
|
|
// NewCluster returns a new, actively-managed Cluster, representing the
|
|
// passed endpoints as Nodes. Each endpoint should be of the form
|
|
// scheme://host:port, for example http://es001:9200.
|
|
//
|
|
// The Cluster will ping each Node on a schedule dictated by pingInterval.
|
|
// Each node has pingTimeout to respond before the ping is marked as failed.
|
|
//
|
|
// TODO node discovery from the list of seed-nodes.
|
|
func NewCluster(endpoints []string, pingInterval, pingTimeout time.Duration) *Cluster {
|
|
nodes := Nodes{}
|
|
for _, endpoint := range endpoints {
|
|
nodes = append(nodes, NewNode(endpoint, pingTimeout))
|
|
}
|
|
|
|
c := &Cluster{
|
|
nodes: nodes,
|
|
pingInterval: pingInterval,
|
|
shutdown: make(chan chan bool),
|
|
}
|
|
go c.loop()
|
|
return c
|
|
}
|
|
|
|
// loop is the event dispatcher for a Cluster. It manages the regular pinging of
|
|
// Nodes, and serves incoming requests. Because every request against the
|
|
// cluster must pass through here, it cannot block.
|
|
func (c *Cluster) loop() {
|
|
ticker := time.Tick(c.pingInterval)
|
|
for {
|
|
select {
|
|
case <-ticker:
|
|
go c.nodes.pingAll()
|
|
|
|
case q := <-c.shutdown:
|
|
q <- true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// Search implements the Searcher interface for a Cluster. It executes the
|
|
// request against a suitable node.
|
|
func (c *Cluster) Search(r SearchRequest) (response SearchResponse, err error) {
|
|
err = c.Execute(r, &response)
|
|
return
|
|
}
|
|
|
|
// MultiSearch implements the MultiSearcher interface for a Cluster. It
|
|
// executes the search request against a suitable node.
|
|
func (c *Cluster) MultiSearch(r MultiSearchRequest) (response MultiSearchResponse, err error) {
|
|
err = c.Execute(r, &response)
|
|
return
|
|
}
|
|
|
|
func (c *Cluster) Index(r IndexRequest) (response IndexResponse, err error) {
|
|
err = c.Execute(r, &response)
|
|
return
|
|
}
|
|
|
|
func (c *Cluster) Create(r CreateRequest) (response IndexResponse, err error) {
|
|
err = c.Execute(r, &response)
|
|
return
|
|
}
|
|
|
|
func (c *Cluster) Update(r UpdateRequest) (response IndexResponse, err error) {
|
|
err = c.Execute(r, &response)
|
|
return
|
|
}
|
|
|
|
func (c *Cluster) Delete(r DeleteRequest) (response IndexResponse, err error) {
|
|
err = c.Execute(r, &response)
|
|
return
|
|
}
|
|
|
|
func (c *Cluster) Bulk(r BulkRequest) (response BulkResponse, err error) {
|
|
err = c.Execute(r, &response)
|
|
return
|
|
}
|
|
|
|
// Executes the request against a suitable node and decodes server's reply into
|
|
// response.
|
|
func (c *Cluster) Execute(f Fireable, response interface{}) error {
|
|
node, err := c.nodes.getBest()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return node.Execute(f, response)
|
|
}
|
|
|
|
// Shutdown terminates the Cluster's event dispatcher.
|
|
func (c *Cluster) Shutdown() {
|
|
q := make(chan bool)
|
|
c.shutdown <- q
|
|
<-q
|
|
}
|