-
Notifications
You must be signed in to change notification settings - Fork 18
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
Optional type as return value of parser calls #51
Comments
@julik I would like to implement this. So here is a code snippet. Here I just return the errors in a hash if the strategy is STRATEGIES = %i[all_results first_result]
def self.parse(io, natures: @parsers_per_nature.keys, formats: @parsers_per_format.keys, strategy: :all_results)
# Check for strategy
unless STRATEGIES.include? strategy
throw ArgumentError.new(
"Uknown strategy #{strategy}. Supported strategies: #{STRATEGIES}."
)
end
# If the cache is preconfigured do not apply an extra layer. It is going
# to be preconfigured when using parse_http.
io = Care::IOWrapper.new(io) unless io.is_a?(Care::IOWrapper)
# Always instantiate parsers fresh for each input, since they might
# contain instance variables which otherwise would have to be reset
# between invocations, and would complicate threading situations
parsers = parsers_for(natures, formats)
parser_errors = {}
results = parsers.lazy.map do |parser|
# We need to rewind for each parser, anew
io.seek(0)
# Limit how many operations the parser can perform
limited_io = ReadLimiter.new(io, max_bytes: MAX_BYTES, max_reads: MAX_READS, max_seeks: MAX_SEEKS)
begin
parser.call(limited_io)
rescue => error
parser_errors[parser.class.name] = error
nil
end
end.reject(&:nil?)
return results.first if strategy == :first_result
{
results: results.to_a,
errors: parser_errors
}
end Could you comment on it? |
Good question. Something like this: https://github.com/WeTransfer/image_vise/blob/master/lib/image_vise/render_engine.rb#L83 In other words, we can have a situation where parsers A and B return a valid result, and parser C errors out. In that case, we need to have some way to communicate that parser C failed to the caller, and maybe use a global FormatParser-configured hook for reporting the error, say, to Appsignal. So by "registering" I mean "communicating". Your idea seems nice, however I think we should return a more "monadic" flat list of parsers + their results or errors. Something like a sum type for |
@julik So each parser would return either a Should this result be encapsulated in a {
result: safe_parse(parser, limited_io) # returns either StandardError, Result or nil
parser: parser.class.name
} Should the |
@WJWH I know what you will say, but we might be needing a sum type or a monad here. Ideas? |
We call parsers in succession, and a single parser failing should not, at least for most errors, lead to other parsers failing as well. We currently capture a tiny subset of errors in the
.parse
method of the FormatParser module, but there is no guarantee these are the only errors a parser could raise.I think what we could use something like this instead:
For this we only have to introduce one wrapper method, and we don't have to change the parsers at all.
The text was updated successfully, but these errors were encountered: