fix panic on POST /transaction on non-primary node

- if we're a non-primary node, redirect to the primary
- if non-primary nodes can create transactions now, then the client should not receive an ErrNotPrimaryNode
- streamline metrics logic
This commit is contained in:
reesporte 2022-01-24 11:01:56 -06:00
parent 1d7a42c7e7
commit 276088c386
3 changed files with 24 additions and 19 deletions

26
api.go
View file

@ -2514,24 +2514,24 @@ func (api *API) StartTransaction(ctx context.Context, id string, timeout time.Du
return nil, errors.Wrap(err, "validating api method")
}
t, err := api.server.StartTransaction(ctx, id, timeout, exclusive, remote)
if exclusive {
switch err {
case nil:
switch err {
case nil:
if exclusive {
api.holder.Stats.Count(MetricExclusiveTransactionRequest, 1, 1.0)
case ErrTransactionExclusive:
api.holder.Stats.Count(MetricExclusiveTransactionBlocked, 1, 1.0)
}
if t.Active {
api.holder.Stats.Count(MetricExclusiveTransactionActive, 1, 1.0)
}
} else {
switch err {
case nil:
} else {
api.holder.Stats.Count(MetricTransactionStart, 1, 1.0)
case ErrTransactionExclusive:
}
case ErrTransactionExclusive:
if exclusive {
api.holder.Stats.Count(MetricExclusiveTransactionBlocked, 1, 1.0)
} else {
api.holder.Stats.Count(MetricTransactionBlocked, 1, 1.0)
}
}
if exclusive && t != nil && t.Active {
api.holder.Stats.Count(MetricExclusiveTransactionActive, 1, 1.0)
}
return t, err
}

View file

@ -14,7 +14,7 @@ import (
"time"
"github.com/davecgh/go-spew/spew"
"github.com/molecula/featurebase/v3"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/http"
"github.com/molecula/featurebase/v3/pql"
"github.com/molecula/featurebase/v3/server"
@ -1419,12 +1419,11 @@ func TestClientTransactions(t *testing.T) {
}
// non-primary
if trns, err := client1.StartTransaction(context.Background(), "blah", time.Minute, false); err == nil ||
!strings.Contains(err.Error(), pilosa.ErrNodeNotPrimary.Error()) {
if trns, err := client1.StartTransaction(context.Background(), "blah", time.Minute, false); err != nil {
t.Fatalf("unexpected error starting on non-primary: %v", err)
} else {
test.CompareTransactions(t,
nil,
&pilosa.Transaction{ID: "blah", Timeout: time.Minute, Active: true, Exclusive: false, Deadline: expDeadline},
trns)
}

View file

@ -2158,9 +2158,15 @@ func (h *Handler) handlePostTransaction(w http.ResponseWriter, r *http.Request)
if !ok {
id = reqTrns.ID
}
trns, err := h.api.StartTransaction(r.Context(), id, reqTrns.Timeout, reqTrns.Exclusive, false)
h.doTransactionResponse(w, err, trns)
if primary := h.api.PrimaryNode(); h.api.NodeID() == primary.ID {
trns, err := h.api.StartTransaction(r.Context(), id, reqTrns.Timeout, reqTrns.Exclusive, false)
h.doTransactionResponse(w, err, trns)
return
} else {
http.Redirect(w, r, primary.URI.Normalize()+"/transaction/"+id, http.StatusSeeOther)
return
}
}
func (h *Handler) handlePostFinishTransaction(w http.ResponseWriter, r *http.Request) {