-
-
Save matthewdale/0605c415fb8bcfbafa2fce5518dce2f7 to your computer and use it in GitHub Desktop.
Go driver unnecessary retry repro (GODRIVER-3145)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"regexp" | |
"strings" | |
"time" | |
"github.com/pterm/pterm" | |
"go.mongodb.org/mongo-driver/bson" | |
"go.mongodb.org/mongo-driver/event" | |
"go.mongodb.org/mongo-driver/mongo" | |
"go.mongodb.org/mongo-driver/mongo/options" | |
"go.mongodb.org/mongo-driver/mongo/readpref" | |
) | |
var eventRegex = regexp.MustCompile("([a-z0-9])([A-Z])") | |
const appName = "GODRIVER-3145" | |
const uri = "mongodb://localhost:27017,localhost:27018,localhost:27019" | |
func main() { | |
bgContext := context.Background() | |
poolMonitor := &event.PoolMonitor{ | |
Event: func(e *event.PoolEvent) { | |
snake := strings.ToLower(eventRegex.ReplaceAllString(e.Type, "${1}_${2}")) | |
name := fmt.Sprintf("pool_event.%s", snake) | |
pterm.Printfln(pterm.Green("Pool Event: %s"), name) | |
}, | |
} | |
opts := options.Client() | |
opts.SetPoolMonitor(poolMonitor) | |
opts.SetAppName(appName) | |
opts.ApplyURI(uri) | |
opts.SetReadPreference(readpref.Primary()) | |
pterm.Printfln(pterm.Blue("Initiating MongoDB Client...")) | |
client, err := mongo.Connect(bgContext, opts) | |
if err != nil { | |
panic(err) | |
} | |
err = client.Ping(bgContext, nil) | |
if err != nil { | |
panic(err) | |
} | |
pterm.Printfln(pterm.Blue("Connected to MongoDB!")) | |
collection := client.Database("test").Collection("test") | |
fastTimeoutCtx, fastQueryCancel := context.WithTimeout(bgContext, 3*time.Second) | |
defer fastQueryCancel() | |
pterm.Printfln(pterm.Blue("Starting fast Mongo Query")) | |
res := collection.FindOne(fastTimeoutCtx, bson.M{}) | |
if res.Err() != nil { | |
pterm.Printfln(pterm.Red("Fast Query Error: %s"), res.Err()) | |
} else { | |
pterm.Println(pterm.Blue("Fast query was successful")) | |
} | |
enableFailpoint() | |
defer disableFailpoint() | |
slowManualTimeoutCtx, slowManualQueryCancel := context.WithCancel(bgContext) | |
go func() { | |
time.Sleep(1 * time.Second) | |
pterm.Printfln(pterm.Red("Manually cancelling slow query")) | |
slowManualQueryCancel() | |
}() | |
pterm.Printfln(pterm.Blue("Starting slow/timeout Mongo Query with manual context cancel")) | |
res = collection.FindOne(slowManualTimeoutCtx, bson.M{"foo": "bar"}) | |
if res.Err() != nil { | |
pterm.Printfln(pterm.Red("Slow Query Manual Cancel Error: %s"), res.Err()) | |
} else { | |
pterm.Println(pterm.Blue("Slow query was successful?????")) | |
} | |
slowDeadlineExceededCtx, slowDeadlineExceededCancel := context.WithTimeout(bgContext, 3*time.Second) | |
defer slowDeadlineExceededCancel() | |
pterm.Printfln(pterm.Blue("Starting slow/timeout Mongo Query with context deadline exceeded")) | |
res = collection.FindOne(slowDeadlineExceededCtx, bson.M{"foo": "bar"}) | |
if res.Err() != nil { | |
pterm.Printfln(pterm.Red("Slow Query Deadline Exceeded Error: %s"), res.Err()) | |
} else { | |
pterm.Println(pterm.Blue("Slow query was successful?????")) | |
} | |
// Give time for any more connection pool events to trigger | |
time.Sleep(5 * time.Second) | |
pterm.Printfln(pterm.Blue("Closing mongodb client")) | |
client.Disconnect(bgContext) | |
} | |
func enableFailpoint() { | |
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(uri)) | |
if err != nil { | |
panic(err) | |
} | |
defer client.Disconnect(context.Background()) | |
failpoint := bson.D{ | |
{"configureFailPoint", "failCommand"}, | |
{"mode", "alwaysOn"}, | |
{"data", bson.D{ | |
{"appName", appName}, | |
{"failCommands", bson.A{"find"}}, | |
{"blockConnection", true}, | |
{"blockTimeMS", 6_000}, | |
}}, | |
} | |
err = client.Database("admin").RunCommand(context.Background(), failpoint).Err() | |
if err != nil { | |
panic(err) | |
} | |
} | |
func disableFailpoint() { | |
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(uri)) | |
if err != nil { | |
panic(err) | |
} | |
defer client.Disconnect(context.Background()) | |
err = client.Database("admin").RunCommand(context.Background(), bson.D{ | |
{"configureFailPoint", "failCommand"}, | |
{"mode", "off"}, | |
}).Err() | |
if err != nil { | |
panic(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment