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

Add Config class for debug, open_timeout, and idle_response_timeout #291

Merged
merged 11 commits into from
Jun 14, 2024

Conversation

nevans
Copy link
Collaborator

@nevans nevans commented Jun 10, 2024

This enables:

  • per-client overrides for Net::IMAP.debug
  • global defaults for open_timeout and idle_response_timeout

This feels like overkill for just these three config values, but it's written in the context of dozens of other future config options as indicated by #288. And this should make adding new config options as simple as adding new attr_accessor (and default values) to the Config class. Regarding the rest of the proposal in #288, this implements the basic config inheritance described there. Note that the backward compatibility load_defaults mentioned by #288 has not been implemented for this PR.

Two other significant implementation details, not originally mentioned in the #288 proposal:

  • basic type checking and coercion has been added. This happened as part of converting the timeouts to use the config: they were already being assigned using Integer(input), so I preserved that.
  • instead of using simple attr_accessor, which was my original plan, this PR delegates to an internal Struct. This is partly a performance optimization (to avoid object shape proliferation), and partly because it simplifies some of the inheritance code.

@nevans nevans changed the title Add Config class for debug, open_timeout, and idle_response_timeout Add Config class for debug, open_timeout, and idle_response_timeout Jun 10, 2024
@nevans nevans force-pushed the config-class branch 2 times, most recently from a769c25 to 926df8c Compare June 10, 2024 12:59
nevans added 11 commits June 11, 2024 22:54
Nothing uses this new Config class yet.  Currently, it holds only three
config options: `debug`, `open_timeout`, and `idle_response_timeout`,
but more will be added soon.

This version does not have any support for inheritance.  That will be
added in one of the next commits.
Config values are stored in a struct rather than ivars to simplify:
* ensuring that all config objects share a single object shape
* querying only locally configured values, e.g for inspection.
Inheritance forms a singly-linked-list, so lookup will be O(n) on the
number of ancestors.  So arbitrarily deep ancestor lists may have poor
performance, but normal cases should be fine.  Without customization,
ancestor trees will be three or four deep:
    client -> [versioned ->] global -> default
Config.global inherits from Config.default
This is implemented as another module included under the other two,
still based on overriding `attr_accessor`.  Types are only enforced by
the attr_writer methods.  Fortunately, rdoc isn't confused by keyword
arguments to `attr_accessor`, so the type can be added to that.

Currently, only `:boolean` and `Integer` are supported, but it should be
easy to add more.
An (unused) client config object has been added to both Net::IMAP and to
ResponseParser.  Every client creates its own config object.  By
default, the client config inherits from the global config.

Unlike the client, which always creates a new Config object, the parser
simply shares the client's config.
In Net::IMAP, the `@@debug` cvar is replaced by `config.debug?`.  And in
ResponseParser, references to the global `Net::IMAP.debug` is replaced
by `config.debug?`.

By default, the client's own config won't have a value set for `debug`,
so it will still inherit from the global `Net::IMAP.config.debug?`.
Since the parser "belongs" to a client, it uses the client's
configuration rather than simply following the global debug mode.
@nevans
Copy link
Collaborator Author

nevans commented Jun 13, 2024

@shugo any objections to this? Honestly, it feels a bit overengineered to me, for just three variables with global defaults and client overrides. But, I'm hoping the inheritance flexibility will pay itself off as more config options are added.

I've updated #97 (with #293) and added #294, based on this config implementation. The only remaining piece to complete #288 is a Config#load_defaults(version).

Also, this is the last significant feature I want for the 0.4 branch. With this in place, we can choose to backport deprecation warnings, with or without any new feature or behavior. For example, I want the default config in v0.6 to disallow all implicit use of RawData, but that requires big updates to search (because currently complex searches need to be sent as a string). Those big updates will not be backported to 0.4, but I may backport the option to enable the deprecation warnings: it would still be useful to get warnings (and maybe convert that code to explicitly use RawData).

@shugo
Copy link
Member

shugo commented Jun 13, 2024

@nevans I'm not against adding Config, but why not just require it instead of autoload?

@nevans
Copy link
Collaborator Author

nevans commented Jun 14, 2024

@nevans I'm not against adding Config, but why not just require it instead of autoload?

Good question. Config will always be loaded. 😆 I switched it to use require.

@nevans nevans merged commit b80fd4c into master Jun 14, 2024
26 checks passed
@nevans nevans deleted the config-class branch June 14, 2024 13:56
@nevans
Copy link
Collaborator Author

nevans commented Jun 14, 2024

@shugo I did switch it to require_relative... but I forgot to push the version where I switched it (and a few other very minor documentation tweaks). I'll push that later today.

nevans added a commit that referenced this pull request Jun 14, 2024
I accidentally merged #291 without pushing this update first!  Oops.

Co-authored-by: Shugo Maeda <shugo@ruby-lang.org>
@nevans
Copy link
Collaborator Author

nevans commented Jun 14, 2024

Pushed the autoload/require_relative switch in #295.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants