Skip to content
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

grid: changing to defered deletion #34832

Merged
merged 12 commits into from
Jun 24, 2024
Merged

Conversation

alyssawilk
Copy link
Contributor

changing the wrapper callbacks and async callbacks in the grid to do deferred deletion.

currently we infer immediate response / async newStream from return codes.
This gets more complicated when we add in happy eyeballs, so instead we want to determine if we should return a cancelable handle based on if the caller has been informed of success or failure. This requires the objects to not be deleted under the stack of newStream hence the migration to defered delete.

Also doing a follow-up from the prior PR and creating connection pools explicitly.

Risk Level: high (object lifetime changes)
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk marked this pull request as draft June 20, 2024 16:50
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

This one in not a hurry as I'm still working on tests for the final PR :-)

Copy link
Contributor

@RyanTheOptimist RyanTheOptimist left a comment

Choose a reason for hiding this comment

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

Nice! I think the getOrCreate is a nice cleanup.

// TODO(alyssawilk) replace this now we have explicit pools.
virtual ConnectionPool::Instance* createNextPool();
// Creates the requested pool
virtual ConnectionPool::Instance* getOrCreateHttp3Pool();
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at the tests, it seems that we really only want to override the "create" part of this method (not the "get" part or the "setupPool" parts, etc). So how 'bout we cook up createHttp3Pool() and createHttp2Pool() and make them virtual. Then they can be called from the non-virutal getOrCreate(). This would simplify the mocking. (Alternatively we could pass two absl::AnyInvokables in the constructor and call them without using any virtual functions.

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.

@@ -324,8 +321,7 @@ ConnectionPool::Cancellable* ConnectivityGrid::newStream(Http::ResponseDecoder&
}
} else {
// Make sure the HTTP/2 pool is created.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can probably delete this comment now since:

pool = getOrCreateHttp2Pool()

is super readable. Woo hoo!

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

@@ -356,8 +351,7 @@ void ConnectivityGrid::addIdleCallback(IdleCb cb) {

void ConnectivityGrid::drainConnections(Envoy::ConnectionPool::DrainBehavior drain_behavior) {
if (drain_behavior == Envoy::ConnectionPool::DrainBehavior::DrainAndDelete) {
// Note that no new pools can be created from this point on
// as createNextPool fast-fails if `draining_` is true.
// Note that no new pools should be created from this point on.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: "should be" => "will be" since this invariant is enforced.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it is, there's just an assert?
we used to handle null pools, now we'll create on drain.

virtual ConnectionPool::Instance* createNextPool();
// Creates the requested pool
virtual ConnectionPool::Instance* getOrCreateHttp3Pool();
virtual ConnectionPool::Instance* getOrCreateHttp2Pool();
Copy link
Contributor

Choose a reason for hiding this comment

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

OOC, can these methods return null? If not, maybe they should return refs? (But I kinda think they can return null?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

they shouldn't return null but the callers want pointers so I didn't think changing the types made sense?

// Creates the next pool in the priority list, or nullptr if all pools have been created.
// TODO(alyssawilk) replace this now we have explicit pools.
virtual ConnectionPool::Instance* createNextPool();
// Creates the requested pool
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: How about "Returns the specified pool, which will be created if necessary"

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

public:
WrapperCallbacks(ConnectivityGrid& grid, Http::ResponseDecoder& decoder,
ConnectionPool::Callbacks& callbacks, const Instance::StreamOptions& options);

bool hasNotifiedCaller() { return inner_callbacks_ == nullptr; }
void deleteIsPending() override { next_attempt_timer_.reset(); }
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the relationship between the next attempt timer and delete pending?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

commented inline

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh! I see. I missed that this was a virtual method as part of Event::DeferredDeletable. Mind adding:
``// Event::DeferredDeletable:`

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

return ret;

// Return a handle if the caller hasn't yet been notified of success/failure.
// Note there may still be connection attempts, if we'e waiting on a slow H3 connection.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: "if we'e waiting on" => "if the TCP attempt is delayed and the H3 attempt is slow" (or somesuch)

go/avoid-we

Copy link
Contributor Author

Choose a reason for hiding this comment

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

rephrased

return nullptr;
ConnectionPool::Instance* getOrCreateHttp3Pool() override {
if (!http3_pool_) {
http3_pool_.reset(createMockPool("http3"));
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: http3_pool_ = createMockPool("http3") (ditto below) or alternatively if we go with making createFooPool() methods, then this is even simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

replaced

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Copy link
Contributor

@RyanTheOptimist RyanTheOptimist left a comment

Choose a reason for hiding this comment

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

Looks great. Two minor comments.

static ConnectionPool::Instance* forceGetOrCreateHttp3Pool(ConnectivityGrid& grid) {
return grid.getOrCreateHttp3Pool();
}
static ConnectionPool::Instance* forceGetOrCreateHttp2Pool(ConnectivityGrid& grid) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Since we're now doing "using ConnectivityGrid::getOrCreateHttp2Pool" do we need this helper function, or can we call grid.getOrCreateHttp2Pool() directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

by default the test grid creates mock pools. This allows forcing a real grid's real pools. commented inline

public:
WrapperCallbacks(ConnectivityGrid& grid, Http::ResponseDecoder& decoder,
ConnectionPool::Callbacks& callbacks, const Instance::StreamOptions& options);

bool hasNotifiedCaller() { return inner_callbacks_ == nullptr; }
void deleteIsPending() override { next_attempt_timer_.reset(); }
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh! I see. I missed that this was a virtual method as part of Event::DeferredDeletable. Mind adding:
``// Event::DeferredDeletable:`

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk enabled auto-merge (squash) June 24, 2024 18:34
@alyssawilk alyssawilk merged commit 243787f into envoyproxy:main Jun 24, 2024
51 of 52 checks passed
antoniovleonti pushed a commit to antoniovleonti/envoy that referenced this pull request Jun 26, 2024
changing the wrapper callbacks and async callbacks in the grid to do deferred deletion.

currently we infer immediate response / async newStream from return codes.
This gets more complicated when we add in happy eyeballs, so instead we want to determine if we should return a cancelable handle based on if the caller has been informed of success or failure. This requires the objects to not be deleted under the stack of newStream hence the migration to defered delete.

Also doing a follow-up from the prior PR and creating connection pools explicitly.

Risk Level: high (object lifetime changes)
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: antoniovleonti <leonti@google.com>
cainelli pushed a commit to cainelli/envoy that referenced this pull request Jul 5, 2024
changing the wrapper callbacks and async callbacks in the grid to do deferred deletion.

currently we infer immediate response / async newStream from return codes.
This gets more complicated when we add in happy eyeballs, so instead we want to determine if we should return a cancelable handle based on if the caller has been informed of success or failure. This requires the objects to not be deleted under the stack of newStream hence the migration to defered delete.

Also doing a follow-up from the prior PR and creating connection pools explicitly.

Risk Level: high (object lifetime changes)
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Fernando Cainelli <fernando.cainelli-external@getyourguide.com>
cainelli pushed a commit to cainelli/envoy that referenced this pull request Jul 5, 2024
changing the wrapper callbacks and async callbacks in the grid to do deferred deletion.

currently we infer immediate response / async newStream from return codes.
This gets more complicated when we add in happy eyeballs, so instead we want to determine if we should return a cancelable handle based on if the caller has been informed of success or failure. This requires the objects to not be deleted under the stack of newStream hence the migration to defered delete.

Also doing a follow-up from the prior PR and creating connection pools explicitly.

Risk Level: high (object lifetime changes)
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Fernando Cainelli <fernando.cainelli-external@getyourguide.com>
cainelli pushed a commit to cainelli/envoy that referenced this pull request Jul 5, 2024
changing the wrapper callbacks and async callbacks in the grid to do deferred deletion.

currently we infer immediate response / async newStream from return codes.
This gets more complicated when we add in happy eyeballs, so instead we want to determine if we should return a cancelable handle based on if the caller has been informed of success or failure. This requires the objects to not be deleted under the stack of newStream hence the migration to defered delete.

Also doing a follow-up from the prior PR and creating connection pools explicitly.

Risk Level: high (object lifetime changes)
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Fernando Cainelli <fernando.cainelli-external@getyourguide.com>
cainelli pushed a commit to cainelli/envoy that referenced this pull request Jul 5, 2024
changing the wrapper callbacks and async callbacks in the grid to do deferred deletion.

currently we infer immediate response / async newStream from return codes.
This gets more complicated when we add in happy eyeballs, so instead we want to determine if we should return a cancelable handle based on if the caller has been informed of success or failure. This requires the objects to not be deleted under the stack of newStream hence the migration to defered delete.

Also doing a follow-up from the prior PR and creating connection pools explicitly.

Risk Level: high (object lifetime changes)
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Fernando Cainelli <fernando.cainelli-external@getyourguide.com>
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.

2 participants