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

Improve table resizing #19

Merged
merged 4 commits into from
Dec 6, 2024
Merged

Improve table resizing #19

merged 4 commits into from
Dec 6, 2024

Conversation

mtrudel
Copy link
Contributor

@mtrudel mtrudel commented Nov 19, 2024

Fixes #18.

  • Introduce a new protocol_max_table_size field on tables, which records the containing protocol (ie: HTTP/2's) view of the max allowable table size. Dynamic resizes validate the new size against this value.
  • Dynamic resizes now update the max_table_size value on tables (evicting as needed to satisfy)
  • Changes to max_protocol_table_size on the encoder are signalled to the decoder via dynamic table size update messages

@coveralls
Copy link

coveralls commented Nov 19, 2024

Pull Request Test Coverage Report for Build 30edd36f7534e73ee1e0eb62fd65de1e40a3be3e-PR-19

Details

  • 21 of 23 (91.3%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.7%) to 93.333%

Changes Missing Coverage Covered Lines Changed/Added Lines %
lib/hpax/table.ex 14 16 87.5%
Totals Coverage Status
Change from base Build 46fece83ea6f7c5c5efa4d6a892a5e28f932b1d0: 0.7%
Covered Lines: 154
Relevant Lines: 165

💛 - Coveralls

@mtrudel
Copy link
Contributor Author

mtrudel commented Nov 29, 2024

@whatyouhide anything you need from me to move this along? I'm keen to get this merged and downstreamed into Bandit as it's blocking real use cases behind AWS load balancers. As I mention in #18, this shouldn't require anything beyond a patch release; there's no user-facing change in either functionality or behaviour.

Copy link
Contributor

@whatyouhide whatyouhide left a comment

Choose a reason for hiding this comment

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

Fantastic work. Left a few small comments but this is ready to go. I was on vacation, sorry 🙃

lib/hpax.ex Outdated
Comment on lines 85 to 87
Resizes the given table to the given maximum size. Intended for use where the
overlying protocol has signalled a change to the table's maximum size,
such as when an HTTP/2 Settings frame is received.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Resizes the given table to the given maximum size. Intended for use where the
overlying protocol has signalled a change to the table's maximum size,
such as when an HTTP/2 Settings frame is received.
Resizes the given table to the given maximum size.
This is intended for use where the
overlying protocol has signaled a change to the table's maximum size,
such as when an HTTP/2 `SETTINGS` frame is received.

lib/hpax.ex Outdated
If the indicated size is less than the table's current size, entries
will be evicted as needed to fit within the specified size, and the table's
maximum size will be decreased to the specified value. A flag will also be
set which will enqueue a 'dynamic table size update' command to be prefixed
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
set which will enqueue a 'dynamic table size update' command to be prefixed
set which will enqueue a "dynamic table size update" command to be prefixed

lib/hpax.ex Outdated
will be evicted as needed to fit within the specified size, and the table's
maximum size will be decreased to the specified value. A flag will also be
set which will enqueue a 'dynamic table size update' command to be prefixed
to the next block encoded with this table, per RFC9113§4.3.1.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you link to that RFC section plz?

lib/hpax.ex Outdated
@@ -149,7 +160,9 @@ defmodule HPAX do
when header: {action, header_name(), header_value()},
action: :store | :store_name | :no_store | :never_store
def encode(headers, %Table{} = table) when is_list(headers) do
encode_headers(headers, table, _acc = [])
{table, pending_resizes} = Table.pending_resizes(table)
acc = pending_resizes |> Enum.map(&[<<0b001::3, Types.encode_integer(&1, 5)::bitstring>>])
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
acc = pending_resizes |> Enum.map(&[<<0b001::3, Types.encode_integer(&1, 5)::bitstring>>])
acc = Enum.map(pending_resizes, &[<<0b001::3, Types.encode_integer(&1, 5)::bitstring>>])


If the existing entries do not fit in the new table size the oldest entries are evicted.
In all cases, the table's protocol_max_table_size is updated accordingly
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
In all cases, the table's protocol_max_table_size is updated accordingly
In all cases, the table's `:protocol_max_table_size` is updated accordingly.

{new_entries_reversed, new_size} = evict_towards_size(Enum.reverse(entries), size, new_size)
def resize(%__MODULE__{max_table_size: max_table_size} = table, new_protocol_max_table_size)
when new_protocol_max_table_size >= max_table_size do
%{
Copy link
Contributor

Choose a reason for hiding this comment

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

Until we have the type system... 😄

Suggested change
%{
%__MODULE__{

Copy link
Contributor

Choose a reason for hiding this comment

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

And in other places too

Additionally, if the current max table size is larger than this value, it is also included int
the list, per https://www.rfc-editor.org/rfc/rfc7541#section-4.2
"""
def pending_resizes(%{pending_minimum_resize: nil} = table), do: {table, []}
Copy link
Contributor

Choose a reason for hiding this comment

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

Since "returns and clears", let's call this

Suggested change
def pending_resizes(%{pending_minimum_resize: nil} = table), do: {table, []}
def pop_pending_resizes(%{pending_minimum_resize: nil} = table), do: {table, []}

?

@mtrudel
Copy link
Contributor Author

mtrudel commented Dec 4, 2024

Issues addressed!

@whatyouhide
Copy link
Contributor

Fantastic work @mtrudel thank you! 💟

@whatyouhide whatyouhide merged commit 708c25d into elixir-mint:main Dec 6, 2024
2 checks passed
@mtrudel mtrudel deleted the fix_resize branch December 6, 2024 13:35
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.

HPAX.resize/2 does not satisfy the requirements of HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE settings updates
3 participants