diff --git a/server/storage/quota.go b/server/storage/quota.go index e15079d45..46b350653 100644 --- a/server/storage/quota.go +++ b/server/storage/quota.go @@ -127,8 +127,13 @@ func NewBackendQuota(cfg config.ServerConfig, be backend.Backend, name string) Q } func (b *BackendQuota) Available(v interface{}) bool { + cost := b.Cost(v) + // if there are no mutating requests, it's safe to pass through + if cost == 0 { + return true + } // TODO: maybe optimize Backend.Size() - return b.be.Size()+int64(b.Cost(v)) < b.maxBackendBytes + return b.be.Size()+int64(cost) < b.maxBackendBytes } func (b *BackendQuota) Cost(v interface{}) int { diff --git a/tests/integration/v3_alarm_test.go b/tests/integration/v3_alarm_test.go index 929d9b926..2fce27bf8 100644 --- a/tests/integration/v3_alarm_test.go +++ b/tests/integration/v3_alarm_test.go @@ -88,6 +88,30 @@ func TestV3StorageQuotaApply(t *testing.T) { } } + // txn with non-mutating Ops should go through when NOSPACE alarm is raised + _, err = kvc0.Txn(context.TODO(), &pb.TxnRequest{ + Compare: []*pb.Compare{ + { + Key: key, + Result: pb.Compare_EQUAL, + Target: pb.Compare_CREATE, + TargetUnion: &pb.Compare_CreateRevision{CreateRevision: 0}, + }, + }, + Success: []*pb.RequestOp{ + { + Request: &pb.RequestOp_RequestDeleteRange{ + RequestDeleteRange: &pb.DeleteRangeRequest{ + Key: key, + }, + }, + }, + }, + }) + if err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithTimeout(context.TODO(), integration.RequestWaitTimeout) defer cancel()