1
0
Fork 0

Allow leader check for queries

master
Philip O Toole 9 years ago
parent a7ade520e4
commit 81a3af3b7e

@ -5,7 +5,6 @@ package http
import (
"encoding/json"
"io/ioutil"
"log"
"net"
"net/http"
"strings"
@ -24,7 +23,7 @@ type Store interface {
// Query executes a slice of queries, each of which returns rows.
// If tx is true, then the query will take place while a read
// transaction is held on the database.
Query(queries []string, tx bool) ([]*sql.Rows, error)
Query(queries []string, tx, leader bool) ([]*sql.Rows, error)
// Join joins the node, reachable at addr, to the cluster.
Join(addr string) error
@ -83,7 +82,7 @@ func (s *Service) Start() error {
go func() {
err := server.Serve(s.ln)
if err != nil {
log.Fatalf("HTTP serve: %s", err)
return
}
}()
@ -254,6 +253,12 @@ func (s *Service) handleQuery(w http.ResponseWriter, r *http.Request) {
return
}
isLeader, err := isLeader(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Get the query statement(s), and do tx if necessary.
queries := []string{}
@ -277,7 +282,7 @@ func (s *Service) handleQuery(w http.ResponseWriter, r *http.Request) {
}
}
results, err := s.store.Query(queries, isTx)
results, err := s.store.Query(queries, isTx, isLeader)
if err != nil {
resp.Error = err.Error()

@ -27,7 +27,7 @@ func Test_404Routes(t *testing.T) {
client := &http.Client{}
resp, err := client.Get(host+"/db/xxx")
resp, err := client.Get(host + "/db/xxx")
if err != nil {
t.Fatalf("failed to make request")
}
@ -55,7 +55,7 @@ func Test_405Routes(t *testing.T) {
client := &http.Client{}
resp, err := client.Get(host+"/db/execute")
resp, err := client.Get(host + "/db/execute")
if err != nil {
t.Fatalf("failed to make request")
}
@ -87,7 +87,7 @@ func (m *MockStore) Execute(queries []string, tx bool) ([]*sql.Result, error) {
return nil, nil
}
func (m *MockStore) Query(queries []string, tx bool) ([]*sql.Rows, error) {
func (m *MockStore) Query(queries []string, tx, leader bool) ([]*sql.Rows, error) {
return nil, nil
}

@ -175,11 +175,15 @@ func (s *Store) Backup() ([]byte, error) {
}
// Query executes queries that return rows, and do not modify the database.
func (s *Store) Query(queries []string, tx bool) ([]*sql.Rows, error) {
func (s *Store) Query(queries []string, tx, leader bool) ([]*sql.Rows, error) {
// Allow concurrent queries.
s.mu.RLock()
defer s.mu.RUnlock()
if leader && s.raft.State() != raft.Leader {
return nil, fmt.Errorf("not leader")
}
r, err := s.db.Query(queries, tx, true)
return r, err
}

Loading…
Cancel
Save