Skip to content

Add ability to observe the number of connections halibut opens for polling connections - #717

Open
pawelpabich wants to merge 6 commits into
mainfrom
pawel/halibut-per-sub-conns
Open

Add ability to observe the number of connections halibut opens for polling connections#717
pawelpabich wants to merge 6 commits into
mainfrom
pawel/halibut-per-sub-conns

Conversation

@pawelpabich

@pawelpabich pawelpabich commented Aug 17, 2026

Copy link
Copy Markdown

await IdentifyAsServerAsync(identity, cancellationToken);
await ProcessClientRequestsAsync(incomingRequestProcessor, cancellationToken);
break;
case RemoteIdentityType.Subscriber:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I've moved the connection limit enforcement closer to the code that it applies to.

  1. There is no need to perform work for other types of remote identities
  2. We were executing IdentifyAsServerAsync even for the default switch case, which results in an exception. This shows how easy it is to make a mistake if code that is case-specific is applied to all cases.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How was the issue found?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I found it by accident

/// <param name="currentCount">
/// The number of active TCP connections for this subscriptionId immediately after the change
/// </param>
public void ConnectionsCountChangedFor(Uri subscriptionId, int previousCount, int currentCount);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I considrerd a pair of ConnectionOpendFor and ConnectionClosedFor methods but then we would keep yet another copy of <SubscriptionId, int> in the metric producer in the server. This might matter when the Server needs to deal with 20k of tentacles. Thoughts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Make it simpler for the caller is probably the best approach.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking at how this is used, what we have now is fine.

readonly HalibutTimeoutsAndLimits timeoutsAndLimits;
readonly IConnectionsObserver connectionsObserver;

Dictionary<Uri, StrongBox<int>> activeConnectionCountPerSubscriptionId = new();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks like the information you want.

Maybe have a method that will give you back a copy of this dictionary upon request.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

That would create a tighter coupling between these two.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think what you are doing with buckets is faster over processing the entire dict each time we want metrics so this is fine.

As for coupling we already have some form, I think the form that works the best for the telemetry we want to collect makes sense. I guess that comes with a "I would be comfortable changing the contract for telemetry callbacks if we had"


count.Value++;

connectionsObserver.ConnectionsCountChangedFor(subscriptionId, previousCount, count.Value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I guess this means we need to be super careful about what ConnectionsCountChangedFor does since slow code here will impact ALL connecting tentacles one after the other.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, the same applies to other methods of the observers. The only difference is that previously only a single connection would be blocked whereas here all new connections would be blocked. Witout the lock, we would get inconsitent results.

@LukeButters LukeButters Sep 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually with your implementation, the call to ConnectionsCountChangedFor does not need to be within the lock provided that the values we would pass in are immutable at this point.

I think I would suggest preserving the values and calling ConnectionsCountChangedFor outside the lock, so as to prevent coupling where someone depends on being within the lock.

I am happy for the PR to go in with the lock around that call but would prefer it not be around the call. We can always move the call to be within the lock later but going the other way is a little more tricky.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Without lock we will be exposed to suprising short term values. E.g.
(1, 2) might be processed before (0, 1) which will result in (-1, 1) -> (0, 1) values in the bucket. (-1, 1) should not really last for long as the connections are rather long lived. I will move it.

@pawelpabich
pawelpabich marked this pull request as ready for review August 25, 2026 01:43
@pawelpabich
pawelpabich requested a review from a team as a code owner August 25, 2026 01:43

@LukeButters LukeButters left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The change: lgtm

I think though it would make sense to have some tests added before merging, could you add some before merging?

@pawelpabich

Copy link
Copy Markdown
Author

Tests added.

@pawelpabich pawelpabich changed the title Add ability to observe the number of connections halibut opens for ea… Add ability to observe the number of connections halibut opens for polling connections Sep 4, 2026
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