-
Notifications
You must be signed in to change notification settings - Fork 31
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
mark ClassHash as shareable, after all classes have been defined #22
Conversation
I was having a look, and there are more places which may need some ractor support fixes. Namely, This logic should however be fine if people instantiate their own resolver class in separate ractors. Any recommendations to work around this? |
Freezing I think making |
Customizing a resolver should require initializing a new instance with the custom class mapping, i.e. the library should not be defining ´ClassHash` as a de-facto lazy cache. just an opinion.
In this case it could work, given that TCP sockets are only used for long DNS answers, and closed afterwards. That'd be different if this were a database pool or smth of the kind, in which case a decision for a "default" would be questionable as well. Ractor-local default resolver could help as well. |
Agreed. DNS has a few (but a growing number of) extension points that allow private/local/experimental use. So, we want some extensible extension mechanism in resolv, which may look like this (just an idea): # resolv
class Resolv::DNS
# Extend Resource::ClassHash & SvcParam::ClassHash to emit deprecation warning on mutation
class ExtensionPoints
#: (Integer, Integer) -> singleton(Resource)
def get_resource_class(type, klass) = Resource.get_class(type, klass)
#: (Integer) -> singleton(SvcParam)
def get_svcparam_class(key) = SvcParam::ClassHash[key]
# In the future, we can add more extension points:
# def get_edns0_option_class(opt) = ...
end
# Opt-in for early adopters
def self.make_shareable
if defined?(Ractor)
Ractor.make_shareable(Resource::ClassHash)
Ractor.make_shareable(SvcParam::ClassHash)
end
end
end
# extension library
module AwesomeResolvExtension
def get_resource_class(type, klass) = (some extension) || super
end
# user code
class MyExtensions < Resolv::DNS::ExtensionPoints
prepend AwesomeResolvExtension
end
@my_resolver = Resolv::DNS.new(..., extensions: MyExtensions.new)
# or maybe
@my_resolver = Resolv::DNS.new(..., extensions: [AwesomeResolvExtension]) After a transition period (maybe a year or two; I'm not sure how long it should be, as resolv is an old library), we can freeze ClassHashes by default and turn Introducing
For the traditional DNS over cleartext TCP, that's right. But, for encrypted protocols such as DNS over TLS, HTTPS, or QUIC, a connection has to be reused for multiple DNS queries to amortize handshake latency and minimize computational cost (It's not very similar to DB pools because these connection-ful DNS transports allow multiplexing query-responses on a single connection). The current DNS trend is transitioning to encryption by default, either by discovery mechanisms like DDR or opportunistic encryption with some heuristics, and I think resolv should adopt it in the future. So, IMHO, we need to design an API supporting such future enhancements before guaranteeing that DefaultResolver is Ractor-shareable. |
FYI, when trying to implement this change in my app, Generic tries to modify the now-frozen ClassHash at line 1774: ClassHash[[type_value, class_value]] = c I just commented it out for myself, but obviously that breaks some functionality |
closing in favour of #62 |
So that Resource classes are usable within ractors.
There's still this function to account for, for which I didn't get the use case. Legitimate to ignore, or worth working around?