-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more queries, fix DB sequence ID's #113
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. Join @richardhuaaa and the rest of your teammates on |
if err != nil { | ||
return fmt.Errorf("unable to insert node info into database: %v", err) | ||
} | ||
|
||
if numRows == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example of where ON CONFLICT DO NOTHING
+ :execRows
is useful
AS $$ | ||
BEGIN | ||
-- Ensures that the generated sequence ID matches the insertion order | ||
-- Only released at the end of the enclosing transaction - beware if called within a long transaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every SQL statement gets wrapped into a transaction if one is not explicitly created, but what we need to be careful of is if application code creates an enclosing transaction that performs a bunch of stuff after this function is called.
If that is needed, the application code can manually wrap the function call in a sub-transaction, to make sure the lock is released in a timely manner.
0c684a8
to
966eb8b
Compare
966eb8b
to
b342aa5
Compare
Great work going deep on these sequencing problems. Unfortunate that we have to use table-level locks, but I don't see much of an alternative. This article is also useful and lists a bunch of alternative solutions to the problem (and why they're all bad). Batching would help a bit, but only if we had enough volume to have large batches in very short time windows. We could always add batching later. |
I've fixed a number of issues, would like to suggest some best practices going forward that I've implemented here:
ON CONFLICT DO NOTHING
clause, and either return the inserted count via:execrows
or the row itself via:one
. This saves the caller from having to parse untyped errors in search of unique constraint violations, which are sometimes expected.RETURNING *
, even if the result is not currently used. This is because any future changes to the function would require a DB migration.queries.sql
, results should be defined as narrowly as possible - for example, do not return the row via:one
if the code is not using it. This saves networking bandwidth, and the query can easily be changed later on without a migration.Node ID
andSequence ID
as the components of aSID
, removing references toLocalID
.Some other stuff I've done:
sid
field in thegateway_envelopes
table intonode_id
andsequence_id
, because the postgresBIGINT
type is a signed 64-bit int that cannot hold auint64
without bad side effects.insert_gateway_envelope
anddelete_staged_originator_envelope
queries which are needed for the stacked PR's.