Skip to content

Conversation

rmloveland
Copy link
Contributor

... and update the surrounding descriptive text to match the new code.

Includes updates based on review comments in #5049, which for some reason stopped accepting updates.

Addresses #5035.

@cockroach-teamcity
Copy link
Member

This change is Reviewable

@rmloveland
Copy link
Contributor Author

Ben, I think I've got this code sample working properly using the recommended txn := db.Begin() ... etc. syntax. In latest commit I added some commented-out retry logic that I was using to test. Didn't squash so the diff would be easy to see.

Based on my tests with a local cluster it is working properly with that update: casting GORM error to pq.Error, checking the code, and running through the loop again maxRetries times before bailing, while using the txn.Foo() statements.

At your convenience do you mind testing it and verifying that it works as it should? Once it looks good to you I'll clean it up by removing the commented out retry stuff, and add in the secure example boilerplate, etc.

@cockroach-teamcity
Copy link
Member

var fromAccount Account
var toAccount Account

db.First(&fromAccount, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These calls must be inside the transaction. Any time the transaction retries, we need to re-query the starting balances. (This applies to the other language examples too).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed these by moving them inside transferFunds, which is now a function argument to a runTransaction function very similar to the Python examples.

}

var maxRetries = 3
for retries := 0; retries <= maxRetries; retries++ {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, you'd want to refactor the retry loop into a higher-order function instead of inlining it in every function that needs a transaction (where supported by the language). I think it's probably a good idea to do that in our examples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. It's pretty close to the Python version but may need some updates to be idiomatic Go. PTAL.

}

txn := db.Begin()
// The statement below is used for forcing transaction retries
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain a little more about what's going on: The first statement in a transaction can be retried transparently on the server, so we need to add a dummy statement so that our force_retry statement isn't the first one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with this explanation.

// The below statement is used for forcing transaction
// retries for verifying the retry loop logic. It is not
// necessary for production code.
// `SELECT crdb_internal.force_retry('1s'::INTERVAL)`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's stylistically weird to insert this at this point. I'd put this in its own txn.Exec statement after the txn.Exec for SELECT now(). This will also force a refactoring to put the error handling in one place (which again would mean making a runTransaction higher-order function)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all refactored into the runTransaction HOF now.

} else {
// Happy case. All went well, so we commit and break out
// of the retry loop.
txn.Commit()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

txn.Commit can return an error which must be handled. In particular it can return a retry error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to check for 40001 errors on txn.Commit() and continue the retry loop if they're encountered.

// retries for verifying the retry loop logic. It is not
// necessary for production code.
// `SELECT crdb_internal.force_retry('1s'::INTERVAL)`,
`UPSERT INTO accounts (id, balance) VALUES
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users of an ORM don't generally want to write SQL queries by hand like this. Idiomatic use of GORM would be to either modify the Account objects and call Save on them or use gorm's Update method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to modify the Account objects and call Save on them.

... and update the surrounding descriptive text to match the new code.

Addresses #5035.
@rmloveland rmloveland force-pushed the 20190710-app-retries-golang branch from 6168247 to ff98e13 Compare August 1, 2019 14:55
@cockroach-teamcity
Copy link
Member

Copy link
Contributor

@bdarnell bdarnell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 2 files at r1, 1 of 1 files at r3.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @bdarnell)


_includes/v19.1/app/insecure/gorm-sample.go, line 41 at r3 (raw file):

	}
	// Used to force a transaction retry.  Can only be run as the
	// 'root' user.

FYI I just filed cockroachdb/cockroach#39243 to change this.

Copy link
Contributor Author

@rmloveland rmloveland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review Ben!

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @bdarnell)


_includes/v19.1/app/insecure/gorm-sample.go, line 41 at r3 (raw file):

Previously, bdarnell (Ben Darnell) wrote…

FYI I just filed cockroachdb/cockroach#39243 to change this.

Good to know, thanks.

Copy link
Contributor

@ericharmeling ericharmeling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM!

@rmloveland rmloveland merged commit 0ab80a9 into master Aug 5, 2019
@rmloveland rmloveland deleted the 20190710-app-retries-golang branch August 5, 2019 14:27
rmloveland added a commit that referenced this pull request Sep 12, 2019
This work was done for 19.1 in #5084 and #5163.  We forgot to also port
it to 19.2.  Hence this commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants