Skip to content

More efficient name-to-id translation#555

Merged
dblock merged 11 commits into
slack-ruby:masterfrom
eizengan:eizengan/efficient_id_transforms
May 14, 2025
Merged

More efficient name-to-id translation#555
dblock merged 11 commits into
slack-ruby:masterfrom
eizengan:eizengan/efficient_id_transforms

Conversation

@eizengan

Copy link
Copy Markdown
Contributor

The conversations_id method paginates with default options over conversations.list responses to find a conversation with a particular name. The conversations.list endpoint has a Tier 2 rate limit, which - when combined with the low default page size - can cause just a single call in a workspace with 2000+ channels to result in rate limiting. This change enables use of non-default page sizes within conversations_id (and id_for, more generally), thus reducing the risk of rate limiting within such workspaces.

@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from 858837b to e9b95e0 Compare April 29, 2025 19:24

@dblock dblock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks, this is a good change. However you should implement it in a way that does not change the existing functionality.

I think we don't want to have to pass the limit all over the place, but to configure it globally and per/client, so follow the existing settings pattern to add it. The default should be no changes, making the API calls as today.

@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch 4 times, most recently from 7b1bf50 to 8097e0b Compare April 30, 2025 14:35
@eizengan

eizengan commented Apr 30, 2025

Copy link
Copy Markdown
Contributor Author

I think we don't want to have to pass the limit all over the place

It's only passed in the one spot, and should probably remain there; if we defer until we're inside id_for we either:

  • lose the context of this being a conversations_id call instead of e.g. users_id, which has a different maximum page size
  • have to build an understanding of the caller inside id_for, (i.e. branch on enum_method)

...implement it in a way that does not change the existing functionality...
...configure it globally and per/client...

Amended, pushed. How do we feel about the name conversations_id_page_size?

The config change does create an unusual codependency between Slack::Web::Api::Mixins::Conversations and Slack::Web::Config, as illustrated by this failing test run. The second commit here provides one possible solution.

@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from 51dec13 to e76942d Compare April 30, 2025 14:40
@eizengan eizengan requested a review from dblock May 2, 2025 15:12

@dblock dblock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are still changing behavior by passing in a page size (100) by default. The code should not be passing anything into limit as before by default to avoid breaking backwards compatibility. I understand this may be the Slack default, or we have default_page_size, but we are relying on this knowledge here.

Stepping back, I propose we add id_for_page_size instead of conversations_id_page_size and implement this inside id_for. It will be simpler and cleaner. Unless you have a reason why this may be a bad idea?

And I'd like to be able to write this, overriding whatever the global id_for_page_size was set to (needs tests):

conversations_id(channel: 'C1234', limit: 10)

This will require passing the limit through, we may want to pass all of options down or add a single limit/page_size parameter.

Sorry to be a pest, hang in here with me :)

Comment thread CHANGELOG.md Outdated
@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from e76942d to 4a87569 Compare May 8, 2025 16:12
@eizengan

eizengan commented May 8, 2025

Copy link
Copy Markdown
Contributor Author

We are still changing behavior by passing in a page size (100) by default.

I think you refer to theh explicit 100 I used to appease the test suite? If so, I'd overlooked the fact we were already doing some stubbing there. Oops! Switched to a stub - no more 100.

Stepping back, I propose we add id_for_page_size instead of conversations_id_page_size and implement this inside id_for. It will be simpler and cleaner. Unless you have a reason why this may be a bad idea?

My only major concern is hypothetical: there might be scenarios where no single page size is good for all translations using id_for. I think we only use this to translate users and channels at present, so my concern may be unwarranted. We can easily pivot to a single id_for_page_size config value if desired.

And I'd like to be able to write this, overriding whatever the global id_for_page_size was set to (needs tests):

conversations_id(channel: 'C1234', limit: 10)

I like it! Coming shortly...

@coveralls

coveralls commented May 8, 2025

Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 15024095954

Details

  • 35 of 35 (100.0%) changed or added relevant lines in 6 files are covered.
  • 4 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.02%) to 90.422%

Files with Coverage Reduction New Missed Lines %
lib/slack/real_time/stores/store.rb 4 77.98%
Totals Coverage Status
Change from base Build 14347505748: -0.02%
Covered Lines: 5853
Relevant Lines: 6473

💛 - Coveralls

@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from 9c11bec to 1d767ca Compare May 8, 2025 16:37
@eizengan

eizengan commented May 8, 2025

Copy link
Copy Markdown
Contributor Author

I've added a couple commits to implement the requested limit parameter and to extend configuration to users_id. We can instead consolidate those config options into a single id_for_page_size quite easily if that's your preference.

@eizengan eizengan requested a review from dblock May 8, 2025 16:39
@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from 1d767ca to a6a86d1 Compare May 8, 2025 16:40

@dblock dblock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Much better!

Add tests for the default value and I think we need to rename things.

:conversations_list,
:channels,
'channel_not_found',
enum_method_options: { limit: limit }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think either we just add one more limit parameter to the already long list of arguments or change the signature to just id_for(options)? WDYT?

If you think both are a bad idea, at a minimum let's rename enum_method_options to just options to be future-proof?

@eizengan

Copy link
Copy Markdown
Contributor Author

Add tests for the default value

Do the changes in the first new commit suffice? I'm not 100% sure on where these should go otherwise. Tests for page size are not present near the other config value tests.

I think either we just add one more limit parameter to the already long list of arguments or change the signature to just id_for(options)? WDYT?

While considering this I noticed a Problem; these methods are often used inside endpoint methods which - as a result of our change - unintentionally pass limit arguments intended for the parent call. I've tentatively renamed our new parameter id_limit to avoid this.

A single options parameter feels fragile to me since it would need exactly the right keys to work correctly. IMO keyword arguments feel like a good choice here.

The second new commit contains changes related to the above issues.

@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch 5 times, most recently from 3cb8c82 to 39b2ece Compare May 12, 2025 16:55
- avoid unintentional parameter forwarding via limit -> id_limit
- switch to keyword parameters
- deduce error text instead of using argument
- enum_method_options -> options
@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from 39b2ece to 1f777a9 Compare May 12, 2025 16:59
@eizengan eizengan requested a review from dblock May 12, 2025 18:05

@dblock dblock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Are we changing default behavior for default page size still, or does it get called with default_page_size anyway today?

Comment thread lib/slack/web/api/mixins/ids.id.rb Outdated
end

it 'translates a channel that starts with a #' do
expect(conversations).to receive(:conversations_list).with(limit: 100)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is a change in default behavior isn't it? This test doesn't pass without the changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah, yes - the old code relies on the default from within the paginator. Hash#compact should suffice to fix this if the defaults are nil; see what you think

@eizengan eizengan requested a review from dblock May 13, 2025 18:30
@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from 451fa7d to 307558b Compare May 13, 2025 18:32
@eizengan

Copy link
Copy Markdown
Contributor Author

Something funky going on in tests - lots of

NameError:
  undefined method 'parse' for class '#<Class:CGI>'

followed by a segfault. Don't have time to dig in at the moment; if you do and hit paydirt, please let me know!

@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch 2 times, most recently from 9dd0007 to 4a1783d Compare May 14, 2025 14:48
@eizengan eizengan force-pushed the eizengan/efficient_id_transforms branch from c97187f to c6e0869 Compare May 14, 2025 14:58
@eizengan

Copy link
Copy Markdown
Contributor Author

Modified your CI so e.g. when ruby-head segfaults during tests Coveralls doesn't panic over the missing test info; ready for re-review

@dblock dblock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks great! Thanks for hanging in here with me.

@dblock dblock merged commit d93052c into slack-ruby:master May 14, 2025
12 checks passed
@eizengan

Copy link
Copy Markdown
Contributor Author

Thanks for hanging in here with me

Not at all; thanks for ensuring additions to this gem are appropriately refined!

@eizengan eizengan deleted the eizengan/efficient_id_transforms branch May 14, 2025 18:27
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