Skip to content

GODRIVER-1901 Add details to wait queue timeout errors #612

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

Merged

Conversation

divjotarora
Copy link
Contributor

This PR modifies the pool type to track the number of connections that are checked out for cursors and transactions. The Connection type increments these statistics when a Pin* function is called and decrements when the connection is expired or returned to the pool. Per the spec, I've also updated the WaitQueueTimeoutError type to include these statistics. They're accessible in code via exported fields on the error type and in the error message generated by the type's Error function.

@divjotarora divjotarora requested a review from benjirewis March 17, 2021 18:31
Copy link
Contributor

@benjirewis benjirewis left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@benjirewis benjirewis left a comment

Choose a reason for hiding this comment

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

LGTM, sorry commented but didn't approve 😆

c.mu.Lock()
defer c.mu.Unlock()
if c.connection == nil {
return fmt.Errorf("attempted to pin a connection for a %s, but the connection has already been returned to the pool", reason)
}

// Only use the provided callbacks for the first reference to avoid double-counting pinned connection statistics
Copy link
Contributor

Choose a reason for hiding this comment

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

I may be misunderstanding something basic. It wasn't clear to me from the design's description of pinning, but is there a case when a cursor or transaction would pin the same connection multiple times? I don't understand why we would ever need to consider the case a connection is pinned multiple times.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Creating a cursor inside a transaction would create two references to the same connection.

assert.Nil(t, err, "PinToTransaction error: %v", err)
assertPoolPinnedStats(t, pool, 0, 1)

err = conn.PinToCursor()
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, maybe this answers my previous question. You may need to pin the same connection to a transaction and a cursor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah right, that's the double counting protection.

errorMsg = fmt.Sprintf("%s; maxPoolSize: %d, connections in use by cursors: %d, connections in use by transactions: %d",
errorMsg, w.maxPoolSize, w.PinnedCursorConnections, w.PinnedTransactionConnections)
return fmt.Sprintf("%s, connections in use by other operations: %d", errorMsg,
w.maxPoolSize-(w.PinnedCursorConnections+w.PinnedTransactionConnections))
Copy link
Contributor

Choose a reason for hiding this comment

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

If I am correct about connections being pinned by both transactions and cursors, is it possible that this could result in a negative number? E.g. max pool size is 1, and the only connection is pinned by both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Connection#pin function always increments the connection's reference count but only calls the provided updatePoolFn for the first reference (see the if c.refCount == 0 conditional). So if a cursor is created in a transaction, the connection reference count should be 2, pool.pinnedCursorConnections should be 0, and pool.pinnedTransactionConnections should be 1. The math shouldn't yield a negative number in this case.

@divjotarora divjotarora requested a review from kevinAlbs March 24, 2021 22:20
Copy link
Contributor

@kevinAlbs kevinAlbs left a comment

Choose a reason for hiding this comment

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

LGTM!

@divjotarora divjotarora force-pushed the godriver1901-lb-timeout-errors branch from 761c97d to a401307 Compare March 24, 2021 22:28
@divjotarora divjotarora merged commit ea02175 into mongodb:master Mar 24, 2021
@divjotarora divjotarora deleted the godriver1901-lb-timeout-errors branch March 24, 2021 22:52
faem pushed a commit to kubedb/mongo-go-driver that referenced this pull request Mar 17, 2022
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.

3 participants