diff --git a/bench_test.go b/bench_test.go new file mode 100644 index 00000000..4495f29f --- /dev/null +++ b/bench_test.go @@ -0,0 +1,43 @@ +package raft + +import ( + "testing" + "time" + + "github.com/hashicorp/go-hclog" +) + +func BenchmarkStoreLogInMem(b *testing.B) { + conf := DefaultConfig() + conf.LocalID = "first" + conf.HeartbeatTimeout = 50 * time.Millisecond + conf.ElectionTimeout = 50 * time.Millisecond + conf.LeaderLeaseTimeout = 50 * time.Millisecond + conf.CommitTimeout = 5 * time.Millisecond + conf.SnapshotThreshold = 100 + conf.TrailingLogs = 10 + conf.LogLevel = "OFF" + raft := MakeRaft(b, conf, true) + raft.logger.SetLevel(hclog.Off) + + NoErr(WaitFor(raft, Leader), b) + + applyAndWait := func(leader *RaftEnv, n, sz int) { + // Do some commits + var futures []ApplyFuture + for i := 0; i < n; i++ { + futures = append(futures, leader.raft.Apply(logBytes(i, sz), 0)) + } + for _, f := range futures { + NoErr(WaitFuture(f), b) + leader.logger.Debug("applied", "index", f.Index(), "size", sz) + } + } + + for i := 0; i < b.N; i++ { + // Do some commits + applyAndWait(raft, 100, 10) + // Do a snapshot + NoErr(WaitFuture(raft.raft.Snapshot()), b) + } +} diff --git a/fuzzy/go.mod b/fuzzy/go.mod index 8980222a..c1c51543 100644 --- a/fuzzy/go.mod +++ b/fuzzy/go.mod @@ -1,14 +1,24 @@ module github.com/hashicorp/raft/fuzzy -go 1.16 +go 1.20 require ( - github.com/boltdb/bolt v1.3.1 // indirect github.com/hashicorp/go-hclog v1.5.0 - github.com/hashicorp/go-msgpack v0.5.5 + github.com/hashicorp/go-msgpack/v2 v2.1.1 github.com/hashicorp/raft v1.2.0 github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea - golang.org/x/sys v0.1.0 // indirect +) + +require ( + github.com/armon/go-metrics v0.4.1 // indirect + github.com/boltdb/bolt v1.3.1 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/hashicorp/go-immutable-radix v1.0.0 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect + github.com/hashicorp/golang-lru v0.5.0 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + golang.org/x/sys v0.13.0 // indirect ) replace github.com/hashicorp/raft => ../ diff --git a/fuzzy/go.sum b/fuzzy/go.sum index e013c3a5..1f99677f 100644 --- a/fuzzy/go.sum +++ b/fuzzy/go.sum @@ -37,6 +37,8 @@ github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxB github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -85,16 +87,11 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -113,8 +110,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -124,6 +121,5 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/fuzzy/transport.go b/fuzzy/transport.go index ba3e8e46..5fdb4c7b 100644 --- a/fuzzy/transport.go +++ b/fuzzy/transport.go @@ -15,7 +15,7 @@ import ( "time" "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-msgpack/codec" + "github.com/hashicorp/go-msgpack/v2/codec" "github.com/hashicorp/raft" ) diff --git a/go.mod b/go.mod index 5850df1c..4cdae5d3 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module github.com/hashicorp/raft -go 1.17 +go 1.20 retract v1.1.3 // Deleted original tag; module checksum may not be accurate. require ( github.com/armon/go-metrics v0.4.1 github.com/hashicorp/go-hclog v1.5.0 - github.com/hashicorp/go-msgpack v0.5.5 + github.com/hashicorp/go-msgpack/v2 v2.1.1 github.com/stretchr/testify v1.8.4 ) @@ -16,9 +16,10 @@ require ( github.com/fatih/color v1.13.0 // indirect github.com/hashicorp/go-immutable-radix v1.0.0 // indirect github.com/hashicorp/golang-lru v0.5.0 // indirect + github.com/kr/pretty v0.2.1 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect + golang.org/x/sys v0.13.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index a4929d7f..a670dd67 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+ github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -45,8 +45,9 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -83,14 +84,10 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -110,18 +107,18 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/integ_test.go b/integ_test.go index 812c5326..61557a35 100644 --- a/integ_test.go +++ b/integ_test.go @@ -70,22 +70,22 @@ func (r *RaftEnv) Restart(t *testing.T) { r.raft = raft } -func MakeRaft(t *testing.T, conf *Config, bootstrap bool) *RaftEnv { +func MakeRaft(tb testing.TB, conf *Config, bootstrap bool) *RaftEnv { // Set the config if conf == nil { - conf = inmemConfig(t) + conf = inmemConfig(tb) } dir, err := os.MkdirTemp("", "raft") if err != nil { - t.Fatalf("err: %v ", err) + tb.Fatalf("err: %v ", err) } stable := NewInmemStore() snap, err := NewFileSnapshotStore(dir, 3, nil) if err != nil { - t.Fatalf("err: %v", err) + tb.Fatalf("err: %v", err) } env := &RaftEnv{ @@ -97,7 +97,7 @@ func MakeRaft(t *testing.T, conf *Config, bootstrap bool) *RaftEnv { } trans, err := NewTCPTransport("localhost:0", nil, 2, time.Second, nil) if err != nil { - t.Fatalf("err: %v", err) + tb.Fatalf("err: %v", err) } env.logger = hclog.New(&hclog.LoggerOptions{ @@ -114,14 +114,14 @@ func MakeRaft(t *testing.T, conf *Config, bootstrap bool) *RaftEnv { }) err = BootstrapCluster(conf, stable, stable, snap, trans, configuration) if err != nil { - t.Fatalf("err: %v", err) + tb.Fatalf("err: %v", err) } } env.logger.Info("starting node", "addr", trans.LocalAddr()) conf.Logger = env.logger raft, err := NewRaft(conf, env.fsm, stable, stable, snap, trans) if err != nil { - t.Fatalf("err: %v", err) + tb.Fatalf("err: %v", err) } env.raft = raft return env @@ -156,7 +156,7 @@ WAIT: goto CHECK } -func WaitFuture(f Future, t *testing.T) error { +func WaitFuture(f Future) error { timer := time.AfterFunc(1000*time.Millisecond, func() { panic(fmt.Errorf("timeout waiting for future %v", f)) }) @@ -164,10 +164,10 @@ func WaitFuture(f Future, t *testing.T) error { return f.Error() } -func NoErr(err error, t *testing.T) { - t.Helper() +func NoErr(err error, tb testing.TB) { + tb.Helper() if err != nil { - t.Fatalf("err: %v", err) + tb.Fatalf("err: %v", err) } } @@ -244,7 +244,7 @@ func TestRaft_Integ(t *testing.T) { futures = append(futures, leader.raft.Apply(logBytes(i, sz), 0)) } for _, f := range futures { - NoErr(WaitFuture(f, t), t) + NoErr(WaitFuture(f), t) leader.logger.Debug("applied", "index", f.Index(), "size", sz) } totalApplied += n @@ -253,7 +253,7 @@ func TestRaft_Integ(t *testing.T) { applyAndWait(env1, 100, 10) // Do a snapshot - NoErr(WaitFuture(env1.raft.Snapshot(), t), t) + NoErr(WaitFuture(env1.raft.Snapshot()), t) // Join a few nodes! var envs []*RaftEnv @@ -261,7 +261,7 @@ func TestRaft_Integ(t *testing.T) { conf.LocalID = ServerID(fmt.Sprintf("next-batch-%d", i)) env := MakeRaft(t, conf, false) addr := env.trans.LocalAddr() - NoErr(WaitFuture(env1.raft.AddVoter(conf.LocalID, addr, 0, 0), t), t) + NoErr(WaitFuture(env1.raft.AddVoter(conf.LocalID, addr, 0, 0)), t) envs = append(envs, env) } @@ -273,7 +273,7 @@ func TestRaft_Integ(t *testing.T) { applyAndWait(leader, 100, 10) // Snapshot the leader - NoErr(WaitFuture(leader.raft.Snapshot(), t), t) + NoErr(WaitFuture(leader.raft.Snapshot()), t) CheckConsistent(append([]*RaftEnv{env1}, envs...), t) @@ -285,7 +285,7 @@ func TestRaft_Integ(t *testing.T) { applyAndWait(leader, 100, 10000) // snapshot the leader [leaders log should be compacted past the disconnected follower log now] - NoErr(WaitFuture(leader.raft.Snapshot(), t), t) + NoErr(WaitFuture(leader.raft.Snapshot()), t) // Unfortunately we need to wait for the leader to start backing off RPCs to the down follower // such that when the follower comes back up it'll run an election before it gets an rpc from @@ -325,7 +325,7 @@ func TestRaft_Integ(t *testing.T) { conf.LocalID = ServerID(fmt.Sprintf("final-batch-%d", i)) env := MakeRaft(t, conf, false) addr := env.trans.LocalAddr() - NoErr(WaitFuture(leader.raft.AddVoter(conf.LocalID, addr, 0, 0), t), t) + NoErr(WaitFuture(leader.raft.AddVoter(conf.LocalID, addr, 0, 0)), t) envs = append(envs, env) leader, err = WaitForAny(Leader, append([]*RaftEnv{env1}, envs...)) @@ -337,8 +337,8 @@ func TestRaft_Integ(t *testing.T) { NoErr(err, t) // Remove the old nodes - NoErr(WaitFuture(leader.raft.RemoveServer(rm1.raft.localID, 0, 0), t), t) - NoErr(WaitFuture(leader.raft.RemoveServer(rm2.raft.localID, 0, 0), t), t) + NoErr(WaitFuture(leader.raft.RemoveServer(rm1.raft.localID, 0, 0)), t) + NoErr(WaitFuture(leader.raft.RemoveServer(rm2.raft.localID, 0, 0)), t) // Shoot the leader env1.Release() @@ -391,7 +391,7 @@ func TestRaft_RestartFollower_LongInitialHeartbeat(t *testing.T) { conf.LocalID = ServerID(fmt.Sprintf("next-batch-%d", i)) env := MakeRaft(t, conf, false) addr := env.trans.LocalAddr() - NoErr(WaitFuture(env1.raft.AddVoter(conf.LocalID, addr, 0, 0), t), t) + NoErr(WaitFuture(env1.raft.AddVoter(conf.LocalID, addr, 0, 0)), t) envs = append(envs, env) } allEnvs := append([]*RaftEnv{env1}, envs...) diff --git a/net_transport.go b/net_transport.go index bf78a481..bc34285e 100644 --- a/net_transport.go +++ b/net_transport.go @@ -14,9 +14,9 @@ import ( "sync" "time" - metrics "github.com/armon/go-metrics" + "github.com/armon/go-metrics" "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-msgpack/codec" + "github.com/hashicorp/go-msgpack/v2/codec" ) const ( @@ -106,6 +106,8 @@ type NetworkTransport struct { timeout time.Duration TimeoutScale int + + msgpackUseNewTimeFormat bool } // NetworkTransportConfig encapsulates configuration for the network transport layer. @@ -157,6 +159,12 @@ type NetworkTransportConfig struct { // Timeout is used to apply I/O deadlines. For InstallSnapshot, we multiply // the timeout by (SnapshotSize / TimeoutScale). Timeout time.Duration + + // MsgpackUseNewTimeFormat when set to true, force the underlying msgpack + // codec to use the new format of time.Time when encoding (used in + // go-msgpack v1.1.5 by default). Decoding is not affected, as all + // go-msgpack v2.1.0+ decoders know how to decode both formats. + MsgpackUseNewTimeFormat bool } // ServerAddressProvider is a target address to which we invoke an RPC when establishing a connection @@ -214,16 +222,17 @@ func NewNetworkTransportWithConfig( maxInFlight = DefaultMaxRPCsInFlight } trans := &NetworkTransport{ - connPool: make(map[ServerAddress][]*netConn), - consumeCh: make(chan RPC), - logger: config.Logger, - maxPool: config.MaxPool, - maxInFlight: maxInFlight, - shutdownCh: make(chan struct{}), - stream: config.Stream, - timeout: config.Timeout, - TimeoutScale: DefaultTimeoutScale, - serverAddressProvider: config.ServerAddressProvider, + connPool: make(map[ServerAddress][]*netConn), + consumeCh: make(chan RPC), + logger: config.Logger, + maxPool: config.MaxPool, + maxInFlight: maxInFlight, + shutdownCh: make(chan struct{}), + stream: config.Stream, + timeout: config.Timeout, + TimeoutScale: DefaultTimeoutScale, + serverAddressProvider: config.ServerAddressProvider, + msgpackUseNewTimeFormat: config.MsgpackUseNewTimeFormat, } // Create the connection context and then start our listener. @@ -407,7 +416,11 @@ func (n *NetworkTransport) getConn(target ServerAddress) (*netConn, error) { w: bufio.NewWriterSize(conn, connSendBufferSize), } - netConn.enc = codec.NewEncoder(netConn.w, &codec.MsgpackHandle{}) + netConn.enc = codec.NewEncoder(netConn.w, &codec.MsgpackHandle{ + BasicHandle: codec.BasicHandle{ + TimeNotBuiltin: !n.msgpackUseNewTimeFormat, + }, + }) // Done return netConn, nil @@ -586,7 +599,11 @@ func (n *NetworkTransport) handleConn(connCtx context.Context, conn net.Conn) { r := bufio.NewReaderSize(conn, connReceiveBufferSize) w := bufio.NewWriter(conn) dec := codec.NewDecoder(r, &codec.MsgpackHandle{}) - enc := codec.NewEncoder(w, &codec.MsgpackHandle{}) + enc := codec.NewEncoder(w, &codec.MsgpackHandle{ + BasicHandle: codec.BasicHandle{ + TimeNotBuiltin: !n.msgpackUseNewTimeFormat, + }, + }) for { select { diff --git a/testing.go b/testing.go index ddb16593..91cf6e76 100644 --- a/testing.go +++ b/testing.go @@ -15,19 +15,19 @@ import ( "time" "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-msgpack/codec" + "github.com/hashicorp/go-msgpack/v2/codec" ) var userSnapshotErrorsOnNoData = true // Return configurations optimized for in-memory -func inmemConfig(t *testing.T) *Config { +func inmemConfig(tb testing.TB) *Config { conf := DefaultConfig() conf.HeartbeatTimeout = 50 * time.Millisecond conf.ElectionTimeout = 50 * time.Millisecond conf.LeaderLeaseTimeout = 50 * time.Millisecond conf.CommitTimeout = 5 * time.Millisecond - conf.Logger = newTestLogger(t) + conf.Logger = newTestLogger(tb) return conf } @@ -175,7 +175,7 @@ func (m *MockMonotonicLogStore) DeleteRange(min uint64, max uint64) error { // map them into calls to testing.T.Log, so that you only see // the logging for failed tests. type testLoggerAdapter struct { - t *testing.T + tb testing.TB prefix string } @@ -185,16 +185,16 @@ func (a *testLoggerAdapter) Write(d []byte) (int, error) { } if a.prefix != "" { l := a.prefix + ": " + string(d) - a.t.Log(l) + a.tb.Log(l) return len(l), nil } - a.t.Log(string(d)) + a.tb.Log(string(d)) return len(d), nil } -func newTestLogger(t *testing.T) hclog.Logger { - return newTestLoggerWithPrefix(t, "") +func newTestLogger(tb testing.TB) hclog.Logger { + return newTestLoggerWithPrefix(tb, "") } // newTestLoggerWithPrefix returns a Logger that can be used in tests. prefix @@ -209,14 +209,14 @@ func newTestLogger(t *testing.T) hclog.Logger { // causes a panic. This is common if you use it for a NetworkTransport for // example and then close the transport at the end of the test because an error // is logged after the test is complete. -func newTestLoggerWithPrefix(t *testing.T, prefix string) hclog.Logger { +func newTestLoggerWithPrefix(tb testing.TB, prefix string) hclog.Logger { if testing.Verbose() { return hclog.New(&hclog.LoggerOptions{Name: prefix}) } return hclog.New(&hclog.LoggerOptions{ Name: prefix, - Output: &testLoggerAdapter{t: t, prefix: prefix}, + Output: &testLoggerAdapter{tb: tb, prefix: prefix}, }) } diff --git a/util.go b/util.go index d427cd61..09c7742b 100644 --- a/util.go +++ b/util.go @@ -12,7 +12,7 @@ import ( "math/rand" "time" - "github.com/hashicorp/go-msgpack/codec" + "github.com/hashicorp/go-msgpack/v2/codec" ) func init() { @@ -129,7 +129,11 @@ func decodeMsgPack(buf []byte, out interface{}) error { // Encode writes an encoded object to a new bytes buffer. func encodeMsgPack(in interface{}) (*bytes.Buffer, error) { buf := bytes.NewBuffer(nil) - hd := codec.MsgpackHandle{} + hd := codec.MsgpackHandle{ + BasicHandle: codec.BasicHandle{ + TimeNotBuiltin: true, + }, + } enc := codec.NewEncoder(buf, &hd) err := enc.Encode(in) return buf, err diff --git a/util_test.go b/util_test.go index 0a450c92..9e3959fd 100644 --- a/util_test.go +++ b/util_test.go @@ -4,11 +4,29 @@ package raft import ( + "bytes" "regexp" "testing" "time" ) +// TestMsgpackEncodeTime ensures that we don't break backwards compatibility when updating go-msgpack with +// Raft binary formats. +func TestMsgpackEncodeTimeDefaultFormat(t *testing.T) { + stamp := "2006-01-02T15:04:05Z" + tm, err := time.Parse(time.RFC3339, stamp) + if err != nil { + t.Fatal(err) + } + buf, err := encodeMsgPack(tm) + + expected := []byte{175, 1, 0, 0, 0, 14, 187, 75, 55, 229, 0, 0, 0, 0, 255, 255} + + if !bytes.Equal(buf.Bytes(), expected) { + t.Errorf("Expected time %s to encode as %+v but got %+v", stamp, expected, buf.Bytes()) + } +} + func TestRandomTimeout(t *testing.T) { start := time.Now() timeout := randomTimeout(time.Millisecond)